[算法]不使用*、/、+、-、%操作符求一个数的1/3

摘要:算法一直是程序员进阶的一道龙门,通常算法都是为了更高效地解决问题而创造的,但也有的只是出于学术性,并不在意其实际意义。这是近日在国外技术问答网站stackoverflow的一个热门问题,不知道你能给出几种解决方法?

导读:算法一直是程序员进阶的一道龙门,通常算法都是为了更高效地解决问题而创造的,但也有的只是出于学术性,并不在意其实际意义。这是近日在国外技术问答网站stackoverflow的一个热门问题,不知道你能给出几种解决方法?

问:在不使用*、/、+、-、%操作符的情况下,如何求一个数的1/3?(用C语言实现)

第一种方法:使用位操作符并实现“+”操作

  1. // 替换加法运算符 
  2. int add(int x, int y) { 
  3.     int a, b; 
  4.     do { 
  5.         a = x & y; 
  6.         b = x ^ y; 
  7.         x = a << 1; 
  8.         y = b; 
  9.     } while (a); 
  10.     return b; 
  11.  
  12. int divideby3 (int num) { 
  13.     int sum = 0; 
  14.     while (num > 3) { 
  15.         sum = add(num >> 2, sum); 
  16.         num = add(num >> 2, num & 3); 
  17.     } 
  18.     if (num == 3) 
  19.         sum = add(sum, 1); 
  20.     return sum;  

原理:n = 4 * a + b; n / 3 = a + (a + b) / 3; 然后 sum += a, n = a + b 并迭代; 当 a == 0 (n < 4)时,sum += floor(n / 3); i.e. 1, if n == 3, else 0

第二种方法:

  1. #include <stdio.h> 
  2. #include <stdlib.h> 
  3. int main() 
  4.     FILE * fp=fopen("temp.dat","w+b"); 
  5.     int number=12346; 
  6.     int divisor=3; 
  7.     char * buf = calloc(number,1); 
  8.     fwrite(buf,number,1,fp); 
  9.     rewind(fp); 
  10.     int result=fread(buf,divisor,number,fp); 
  11.     printf("%d / %d = %d", number, divisor, result); 
  12.     free(buf); 
  13.     fclose(fp); 
  14.     return 0; 

第三种方法:

  1. log(pow(exp(number),0.33333333333333333333)) /* :-) */ 

增强版:

  1. log(pow(exp(number),sin(atan2(1,sqrt(8)))))  

第四种方法:

  1. #include <stdio.h> 
  2. #include <stdlib.h> 
  3. int main(int argc, char *argv[]) 
  4.     int num = 1234567; 
  5.     int den = 3; 
  6.     div_t r = div(num,den); // div()是标准C语言函数
  7.     printf("%d\n", r.quot); 
  8.     return 0; 

第五种方法:使用内联汇编

  1. #include <stdio.h> 
  2. int main() { 
  3.   int dividend = -42, divisor = 3, quotient, remainder; 
  4.  
  5.   __asm__ ( "movl   %2, %%edx;" 
  6.             "sarl  $31, %%edx;" 
  7.             "movl   %2, %%eax;" 
  8.             "movl   %3, %%ebx;" 
  9.             "idivl      %%ebx;" 
  10.           : "=a" (quotient), "=d" (remainder) 
  11.           : "g"  (dividend), "g"  (divisor) 
  12.           : "ebx" ); 
  13.  
  14.   printf("%i / %i = %i, remainder: %i\n", dividend, divisor, quotient, remainder); 

第六种方法:

  1. // 注意: itoa 不是个标准函数,但它可以实现
  2. // don't seem to handle negative when base != 10 
  3. int div3(int i) { 
  4.   char str[42]; 
  5.   sprintf(str, "%d", INT_MIN); // put minus sign at str[0] 
  6.   if (i>0) str[0] = ' ';       // remove sign if positive 
  7.   itoa(abs(i), &str[1], 3);    // put ternary absolute value starting at str[1] 
  8.   str[strlen(&str[1])] = '\0'// drop last digit 
  9.   return strtol(str, NULL, 3); // read back result 

第七种方法:

  1. unsigned div_by(unsigned const x, unsigned const by) { 
  2.   unsigned floor = 0; 
  3.   for (unsigned cmp = 0, r = 0; cmp <= x;) { 
  4.     for (unsigned i = 0; i < by; i++) 
  5.       cmp++; // 这是++操作符,不是+ 
  6.     floor = r; 
  7.     r++; // 这也不是 
  8.   } 
  9.   return floor; 

替换掉上面算法的++运算符:

  1. unsigned inc(unsigned x) { 
  2.   for (unsigned mask = 1; mask; mask <<= 1) { 
  3.     if (mask & x) 
  4.       x &= ~mask; 
  5.     else 
  6.       return x & mask; 
  7.   } 
  8.   return 0; // 溢出(注意:这里的x和mask都是0)

这个版本更快一些:

  1. unsigned add(char const zero[], unsigned const x, unsigned const y) { 
  2.   // 这是因为:如果foo是char*类型, &foo[bar] == foo+bar
  3.   return (int)(uintptr_t)(&((&zero[x])[y])); 
  4.  
  5. unsigned div_by(unsigned const x, unsigned const by) { 
  6.   unsigned floor = 0; 
  7.   for (unsigned cmp = 0, r = 0; cmp <= x;) { 
  8.     cmp = add(0,cmp,by); 
  9.     floor = r; 
  10.     r = add(0,r,1); 
  11.   } 
  12.   return floor; 

第八种方法:实现乘法

  1. int mul(int const x, int const y) { 
  2.   return sizeof(struct { 
  3.     char const ignore[y]; 
  4.   }[x]); 

第九种方法:极限

  1. public static int div_by_3(long a) { 
  2.     a <<= 30; 
  3.     for(int i = 2; i <= 32 ; i <<= 1) { 
  4.         a = add(a, a >> i); 
  5.     } 
  6.     return (int) (a >> 32); 
  7.  
  8. public static long add(long a, long b) { 
  9.     long carry = (a & b) << 1; 
  10.     long sum = (a ^ b); 
  11.     return carry == 0 ? sum : add(carry, sum); 

原理:

因为, 1/3 = 1/4 + 1/16 + 1/64 + ...

所以,

a/3 = a * 1/3  

a/3 = a * (1/4 + 1/16 + 1/64 + ...)

a/3 = a/4 + a/16 + 1/64 + ...

a/3 = a >> 2 + a >> 4 + a >> 6 + ...

第十种方法:

  1. public static int DivideBy3(int a) { 
  2.     bool negative = a < 0
  3.     if (negative) a = Negate(a); 
  4.     int result; 
  5.     int sub = 3 << 29
  6.     int threes = 1 << 29
  7.     result = 0
  8.     while (threes > 0) { 
  9.         if (a >= sub) { 
  10.             a = Add(a, Negate(sub)); 
  11.             result = Add(result, threes); 
  12.         } 
  13.         sub >>= 1; 
  14.         threes >>= 1; 
  15.     } 
  16.     if (negative) result = Negate(result); 
  17.     return result; 
  18. public static int Negate(int a) { 
  19.     return Add(~a, 1); 
  20. public static int Add(int a, int b) { 
  21.     int x = 0
  22.     x = a ^ b; 
  23.     while ((a & b) != 0) { 
  24.         b = (a & b) << 1
  25.         a = x
  26.         x = a ^ b; 
  27.     } 
  28.     return x; 

注:本例是C#实现,因为作者更熟悉C#,但本题更倾向于算法,所以语言并不是太重要吧?(当然只是在不使用语言特性的前提下。)

如果你还想了解更多的方法可以点击这里。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/450802.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

2022届互联网秋招备战

文章目录1、何为秋招&#xff1f;1.1应届生身份1.2秋招、春招、校招1.3、社招、海投2.秋招信息如何获取&#xff1f;3、如何备战秋招&#xff1f;3.1、简历&#xff08;ps做简历&#xff09;3.2、笔试准备3.3、面试准备4、日常实习和暑假实习&#xff1f;1、春招≠暑期实习2、什…

php 两变量值互换 方法

//方法一&#xff1a;$a "abc";$b"def";$a $a^$b;$b $b^$a;$a $a^$b;//方法二&#xff1a;list($a, $b) array($b, $a);//方法三&#xff1a;$a $a . $b;$b strlen( $b );$b substr( $a,0,(strlen($a)- $b ));$a substr( $a, strlen($b));//方法四&…

MySQL5.7 group by新特性,报错1055

项目中本来使用的是mysql5.6进行开发&#xff0c;切换到5.7之后&#xff0c;突然发现原来的一些sql运行都报错&#xff0c;错误编码1055&#xff0c;错误信息和sql_mode中的“only_full_group_by“关&#xff0c;到网上看了原因&#xff0c;说是mysql5.7中only_full_group_by这…

IDEA中多行注释及取消注释快捷键

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 1、一次性添加多行注释的快捷键 首先选中要注释区域&#xff0c;然后 ctrl/ 这个是多行代码分行注释&#xff0c;每行一个注释…

为什么程序员不擅长估算时间?

摘要&#xff1a;时间估算是困难的&#xff0c;每一个程序员都有一个现实的估计区间&#xff0c;低于这个区间的估计意味着&#xff08;构件&#xff0c;测试&#xff0c;检查代码的&#xff09;时间开销被低估了&#xff0c;超过这个区间的估计意味着这个任务太大而很难预估。…

red hat enterprise linux 7关闭防火墙的方法

2019独角兽企业重金招聘Python工程师标准>>> red hat enterprise linux 7发布后&#xff0c;发现防火墙也变了&#xff0c;如何关闭防火墙呢&#xff0c;下面是方法 1.查看firewall的状态 [rootsztech7 ~]# systemctl status firewalld firewalld.service - firewal…

IOS —— 网络那些事(上) - http协议

作为一名并不太合格的程序员&#xff0c;今天要分享学习的成果&#xff0c;竟然讲的是网络相关HTTP协议的事情。&#xff08;也算是复习了&#xff09; 乍看HTTP协议的内容着实是十分复杂的&#xff0c;涉及到十分多互联网"底层"框架的东西。今天就先撇开这部分详细内…

【最新版】Java速成路线(急于找工作!)

文章目录计算机网络分层结构TCP/UDPHTTP/HTTPS状态码Cookie 和 SessionURI和URL操作系统线程和进程数据结构和算法数据结构算法设计模式&#xff08;23种&#xff09;单例工厂代理适配器观察者模板实操工具Git/SVNMaven/GradleLinux基本操作NginxELKpostmanJAVA基础语言基础JVM…

Java Web Start实例

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 JWS让用户可以下载服务器端的Java Application到本机运行&#xff0c;并且没有安装、配置等繁琐的操作JWS的运行原理&#xff1a;浏览器…

老派程序员——徒手实现伟大成就

摘要&#xff1a;本文介绍了三位非常著名的程序员&#xff1a;Ken Thompson,Joe Armstrong 和 Jamie Zawinski&#xff0c;他们是如何发明一门新语言&#xff0c;他们开发软件时会像我们一样使用当今流行的开发工具吗&#xff1f;当读Peter Seibel的精彩著作《编程人生:15位软件…

互联网大厂项目研发流程

文章目录阶段一&#xff1a;阶段二&#xff1a;阶段三&#xff1a;阶段四&#xff1a;阶段五&#xff1a;开发人员&#xff1a;测试人员&#xff1a;设计师&#xff1a;阶段六&#xff1a;阶段七&#xff1a;总结&#xff1a;本文章学习自&#xff1a;https://www.bilibili.com…

centos常见错误 Failed to set locale, defaulting to C

错误描述&#xff1a; 当在centos中使用yum命令时&#xff0c;输出错误&#xff1a; [rootlocalhost yum.repos.d]# yum list |grep prceFailed to set locale, defaulting to C 用locale检测&#xff0c;出现如下提示&#xff1a; rootlocalhost yum.repos.d]# localelocale: …

图片上传知识点梳理

在日常项目开发中&#xff0c;图片上传是一个十分常见的场景。而现在的各种UI框架都提供了自己的上传组件&#xff0c;网上第三方的上传组件也多如牛毛。可能你早已习惯了直接使用这些现成的组件&#xff0c;然而对于其具体的实现&#xff0c;却并未深入解析。本文将通过简单的…

解决 java.lang.IllegalArgumentException: Repository interface must not be null on initialization!

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 报错&#xff1a;Caused by: java.lang.IllegalArgumentException: Repository interface must not be null on initialization! Cause…

【狂神说】JVM

文章目录1.JVM的位置2.JVM的体系结构3.类加载器4.双亲委派机制&#xff08;重要&#xff09;5.沙箱安全机制(了解)6.native&#xff08;核心&#xff09;7.PC寄存器&#xff08;了解&#xff09;8.方法区9.栈10.三种JVM11.堆&#xff08;Heap&#xff09;12.新生区、老年区13.永…

我们真的需要统一的编程规范?

摘要&#xff1a;仁者见仁智者见智&#xff0c;编码风格的不同&#xff0c;对项目也会有不同的影响&#xff0c;统一的编码规范有益于项目的维护。俗话说&#xff0c;没有规矩不成方圆&#xff0c;在2004年&#xff0c;UNIX创始人之一的Ken Arnold就发表了一篇很幽默文章&#…

百度云重磅发布ABC 3.0 尹世明如何诠释百度云的“新”打法

雷锋网9月4日消息&#xff0c;2018百度云智峰会正式召开&#xff0c;百度总裁张亚勤发表题为《新技术驱动&#xff0c;全面进入Cloud2.0》的演讲并表示&#xff0c;经历了PCClient/Server到MobileCloud 1.0&#xff0c;再到如今的AICloud 2.0过程&#xff0c;新技术推动云计算产…

EcmaScript对象克隆之谜

先谈谈深拷贝 如何在js中获得一个克隆对象&#xff0c;可以说是喜闻乐见的话题了。相信大家都了解引用类型与基本类型&#xff0c;也都知道有种叫做深拷贝的东西&#xff0c;传说深拷贝可以获得一个克隆对象&#xff01;那么像我这样的萌新自然就去学习了一波&#xff0c;我们能…

开发人员眼中最好的代码编辑器是谁?

摘要&#xff1a;对开发人员来讲&#xff0c;开发工具就好比战场上的“兵器”&#xff0c;不同领域的开发人员他们所使用的“兵器”也不完全相同&#xff0c;本文从友好性、功能性、扩展等多方面总结了最受开发人员欢迎的“兵器”。你最爱的那个在这里吗&#xff1f; 如果我们把…

关于RESTful一些注意事项,接口开发规范

前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到教程。 最近在研究restful&#xff0c;公司开发要使用&#xff0c;所以自己就去网上找了好些资料&#xff0c;并整理了一套公司开发的接口规范。…