生活随笔
收集整理的這篇文章主要介紹了
[算法]不使用*、/、+、-、%操作符求一个数的1/3
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
摘要:算法一直是程序員進階的一道龍門,通常算法都是為了更高效地解決問題而創造的,但也有的只是出于學術性,并不在意其實際意義。這是近日在國外技術問答網站stackoverflow的一個熱門問題,不知道你能給出幾種解決方法?
導讀:算法一直是程序員進階的一道龍門,通常算法都是為了更高效地解決問題而創造的,但也有的只是出于學術性,并不在意其實際意義。這是近日在國外技術問答網站stackoverflow的一個熱門問題,不知道你能給出幾種解決方法?
問:在不使用*、/、+、-、%操作符的情況下,如何求一個數的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);?????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);?}?
第六種方法:
?int?div3(int?i)?{???char?str[42];???sprintf(str,?"%d",?INT_MIN);????if?(i>0)?str[0]?=?'?';??????????itoa(abs(i),?&str[1],?3);???????str[strlen(&str[1])]?=?'\0';????return?strtol(str,?NULL,?3);??}?
第七種方法:
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;?}?
這個版本更快一些:
unsigned?add(char?const?zero[],?unsigned?const?x,?unsigned?const?y)?{?????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;?}?
注:本例是C#實現,因為作者更熟悉C#,但本題更傾向于算法,所以語言并不是太重要吧?(當然只是在不使用語言特性的前提下。)
如果你還想了解更多的方法可以點擊這里。
總結
以上是生活随笔為你收集整理的[算法]不使用*、/、+、-、%操作符求一个数的1/3的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。