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

来源:互联网 发布:易语言获取js后的源码 编辑:程序博客网 时间:2024/06/13 13:03

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

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

// 替换加法运算符 int add(int x, int y) {     int a, b;     do {         a = x & y;         b = x ^ y;         x = a << 1;         y = b;     } while (a);     return b; }  int divideby3 (int num) {     int sum = 0;     while (num > 3) {         sum = add(num >> 2, sum);         num = add(num >> 2, num & 3);     }     if (num == 3)         sum = add(sum, 1);     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

第二种方法:

#include <stdio.h> #include <stdlib.h> int main() {     FILE * fp=fopen("temp.dat","w+b");     int number=12346;     int divisor=3;     char * buf = calloc(number,1);     fwrite(buf,number,1,fp);     rewind(fp);     int result=fread(buf,divisor,number,fp);     printf("%d / %d = %d", number, divisor, result);     free(buf);     fclose(fp);     return 0; } 

第三种方法:

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

增强版:

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

第四种方法:

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

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

#include <stdio.h> int main() {   int dividend = -42, divisor = 3, quotient, remainder;    __asm__ ( "movl   %2, %%edx;"             "sarl  $31, %%edx;"             "movl   %2, %%eax;"             "movl   %3, %%ebx;"             "idivl      %%ebx;"           : "=a" (quotient), "=d" (remainder)           : "g"  (dividend), "g"  (divisor)           : "ebx" );    printf("%i / %i = %i, remainder: %i\n", dividend, divisor, quotient, remainder); } 

第六种方法:

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

第七种方法:

unsigned div_by(unsigned const x, unsigned const by) {   unsigned floor = 0;   for (unsigned cmp = 0, r = 0; cmp <= x;) {     for (unsigned i = 0; i < by; i++)       cmp++; // 这是++操作符,不是+     floor = r;     r++; // 这也不是   }   return floor; } 

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

unsigned inc(unsigned x) {   for (unsigned mask = 1; mask; mask <<= 1) {     if (mask & x)       x &= ~mask;     else       return x & mask;   }   return 0; // 溢出(注意:这里的x和mask都是0)} 

这个版本更快一些:

unsigned add(char const zero[], unsigned const x, unsigned const y) {   // 这是因为:如果foo是char*类型, &foo[bar] == foo+bar  return (int)(uintptr_t)(&((&zero[x])[y])); }  unsigned div_by(unsigned const x, unsigned const by) {   unsigned floor = 0;   for (unsigned cmp = 0, r = 0; cmp <= x;) {     cmp = add(0,cmp,by);     floor = r;     r = add(0,r,1);   }   return floor; } 

第八种方法:实现乘法

int mul(int const x, int const y) {   return sizeof(struct {     char const ignore[y];   }[x]); } 

第九种方法:极限

public static int div_by_3(long a) {     a <<= 30;     for(int i = 2; i <= 32 ; i <<= 1) {         a = add(a, a >> i);     }     return (int) (a >> 32); }  public static long add(long a, long b) {     long carry = (a & b) << 1;     long sum = (a ^ b);     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 + ...

第十种方法:

public static int DivideBy3(int a) {     bool negative = a < 0;     if (negative) a = Negate(a);     int result;     int sub = 3 << 29;     int threes = 1 << 29;     result = 0;     while (threes > 0) {         if (a >= sub) {             a = Add(a, Negate(sub));             result = Add(result, threes);         }         sub >>= 1;         threes >>= 1;     }     if (negative) result = Negate(result);     return result; } public static int Negate(int a) {     return Add(~a, 1); } public static int Add(int a, int b) {     int x = 0;     x = a ^ b;     while ((a & b) != 0) {         b = (a & b) << 1;         a = x;         x = a ^ b;     }     return x; } 


0 0
原创粉丝点击