在不使用*、/、+、-、%操作符的情况下,如何求一个数的1/3

导读:算法一直是程序员进阶的一道龙门,通常算法都是为了更高效地解决问题而创造的,但也有的只是出于学术性,并不在意其实际意义。这是近日在国外技术问答网站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; 
<think>我们参考引用[1],[2],[4]中的方法,使用switch语句实现输入两个一个操作符(+-*/)并输出计算结果。 注意:对于除法,我们需要处理除为0的情况,并且当进行除法时,为了得到精确结果,应该将结果转换为浮点(如引用[4]的做法)。 但引用[2]中直接输出整除法结果,而引用[4]则对除法做了特殊处理(转换为浮点)。这里我们可以根据需选择:如果希望除法得到小,则用浮点;如果希望整除法,则用整。 另外,我们还要考虑操作符的合法性(如果是+-*/则提示错误)。 步骤: 1. 定义两个整变量和一个字符变量(操作符)。 2. 输入两个整一个操作符3. 使用switch语句,根据操作符进行同的运算。 4. 对于除法,检查除是否为0,若为0则报错。 5. 输出计算结果。 我们将分别处理整运算(加减乘)和除法(浮点)的情况,但为了输出的一致性,我们可以考虑将除法的结果单独处理为浮点,而其他运算为整。 另外,引用[4]中在default分支处理除法,但我们建议单独处理除法(在case &#39;/&#39;中处理),而将其他非法运算符放在default分支处理。 代码实现: </think># C语言使用switch语句实现简易计算器 下面是一个使用switch语句实现的计算器程序,可以输入两个整和运算符(+-*/)并输出计算结果: ```c #include <stdio.h> int main() { int num1, num2; char operator; // 输入两个整和运算符 printf("请输入两个整一个运算符(格式: 1 字2 运算符): "); scanf("%d %d %c", &num1, &num2, &operator); // 使用switch语句根据运算符进行计算 switch(operator) { case &#39;+&#39;: printf("%d + %d = %d\n", num1, num2, num1 + num2); break; case &#39;-&#39;: printf("%d - %d = %d\n", num1, num2, num1 - num2); break; case &#39;*&#39;: printf("%d * %d = %d\n", num1, num2, num1 * num2); break; case &#39;/&#39;: // 处理除为0的情况 if(num2 == 0) { printf("错误:除能为0!\n"); } else { // 将结果转换为浮点以获得小部分 printf("%d / %d = %.2f\n", num1, num2, (float)num1 / num2); } break; default: printf("错误:无效的运算符 &#39;%c&#39;!\n", operator); printf("支持的运算符: + - * /\n"); } return 0; } ``` ## 代码说明 1. **输入处理**: - 使用`scanf`接收两个整一个运算符 - 输入格式示例:`5 3 +` 或 `10 2 /` 2. **switch语句实现**: - `case &#39;+&#39;`:执行加法运算 - `case &#39;-&#39;`:执行减法运算 - `case &#39;*&#39;`:执行乘法运算 - `case &#39;/&#39;`:执行除法运算(含除零检查) - `default`:处理无效运算符输入 3. **除法处理**: - 检查除是否为0,避免除零错误 - 使用`(float)num1 / num2`将结果转换为浮点,保留小部分 - 输出格式化使用`%.2f`保留两位小 ## 运行示例 ``` 请输入两个整一个运算符(格式: 1 字2 运算符): 8 3 * 8 * 3 = 24 请输入两个整一个运算符(格式: 1 字2 运算符): 15 4 / 15 / 4 = 3.75 请输入两个整一个运算符(格式: 1 字2 运算符): 10 0 / 错误:除能为0! 请输入两个整一个运算符(格式: 1 字2 运算符): 5 3 % 错误:无效的运算符 &#39;%&#39;! 支持的运算符: + - * / ``` ## 算法原理 该程序使用switch语句实现了简单的四则运算功能,其核心逻辑如下: 1. 输入两个操作一个运算符 2. 根据运算符类型执行相应分支: - 加法:$a + b$ - 减法:$a - b$ - 乘法:$a \times b$ - 除法:$\frac{a}{b}$(需$b \neq 0$) 3. 格式化输出计算结果 这种实现方式简洁清晰,通过switch语句将同运算符的处理逻辑分离,提高了代码可读性[^1][^2][^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值