【算法】不使用*、/、+、-、%操做符求一個數的1/3

問:在不使用*、/、+、-、%操做符的狀況下,如何求一個數的1/3?(用C語言實現)git

第一種方法:使用位操做符並實現「+」操做
// 替換加法運算符 
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 0ide

第二種方法:
#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; 
函數

ui

第三種方法:
log(pow(exp(number),0.33333333333333333333)) /* :-) */ 
加強版:
three

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

第四種方法:
#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; 
it

io

第五種方法:使用內聯彙編
#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); 
asm

第六種方法:
// 注意: 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&gt;0) str[0] = ' ';       // remove sign if positive 
  itoa(abs(i), &amp;str[1], 3);    // put ternary absolute value starting at str[1] 
  str[strlen(&amp;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 &lt;= x;) { 
    for (unsigned i = 0; i &lt; by; i++) 
      cmp++; // 這是++操做符,不是+ 
    floor = r; 
    r++; // 這也不是 
  } 
  return floor; 

替換掉上面算法的++運算符:
unsigned inc(unsigned x) { 
  for (unsigned mask = 1; mask; mask &lt;&lt;= 1) { 
    if (mask &amp; x) 
      x &amp;= ~mask; 
    else 
      return x &amp; mask; 
  } 
  return 0; // 溢出(注意:這裏的x和mask都是0) 

這個版本更快一些:
unsigned add(char const zero[], unsigned const x, unsigned const y) { 
  // 這是由於:若是foo是char*類型, &amp;foo[bar] == foo+bar 
  return (int)(uintptr_t)(&amp;((&amp;zero[x])[y])); 

unsigned div_by(unsigned const x, unsigned const by) { 
  unsigned floor = 0; 
  for (unsigned cmp = 0, r = 0; cmp &lt;= 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 &lt;&lt;= 30; 
    for(int i = 2; i &lt;= 32 ; i &lt;&lt;= 1) { 
        a = add(a, a &gt;&gt; i); 
    } 
    return (int) (a &gt;&gt; 32); 

public static long add(long a, long b) { 
    long carry = (a &amp; b) &lt;&lt; 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 &gt;&gt; 2 + a &gt;&gt; 4 + a &gt;&gt; 6 + ...

第十種方法: public static int DivideBy3(int a) {      bool negative = a &lt; 0;      if (negative) a = Negate(a);      int result;      int sub = 3 &lt;&lt; 29;      int threes = 1 &lt;&lt; 29;      result = 0;      while (threes &gt; 0) {          if (a &gt;= sub) {              a = Add(a, Negate(sub));              result = Add(result, threes);          }          sub &gt;&gt;= 1;          threes &gt;&gt;= 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 &amp; b) != 0) {          b = (a &amp; b) &lt;&lt; 1;          a = x;          x = a ^ b;      }      return x;  }  注:本例是C#實現,由於做者更熟悉C#,但本題更傾向於算法,因此語言並非過重要吧?(固然只是在不使用語言特性的前提下。)</stdio.h></stdlib.h></stdio.h></stdlib.h></stdio.h>

相關文章
相關標籤/搜索