生活随笔
收集整理的這篇文章主要介紹了
[算法]不使用*、/、+、-、%操作符求一个数的1/3
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
摘要:算法一直是程序員進(jìn)階的一道龍門(mén),通常算法都是為了更高效地解決問(wèn)題而創(chuàng)造的,但也有的只是出于學(xué)術(shù)性,并不在意其實(shí)際意義。這是近日在國(guó)外技術(shù)問(wèn)答網(wǎng)站stackoverflow的一個(gè)熱門(mén)問(wèn)題,不知道你能給出幾種解決方法?
導(dǎo)讀:算法一直是程序員進(jìn)階的一道龍門(mén),通常算法都是為了更高效地解決問(wèn)題而創(chuàng)造的,但也有的只是出于學(xué)術(shù)性,并不在意其實(shí)際意義。這是近日在國(guó)外技術(shù)問(wèn)答網(wǎng)站stackoverflow的一個(gè)熱門(mén)問(wèn)題,不知道你能給出幾種解決方法?
問(wèn):在不使用*、/、+、-、%操作符的情況下,如何求一個(gè)數(shù)的1/3?(用C語(yǔ)言實(shí)現(xiàn))
第一種方法:使用位操作符并實(shí)現(xiàn)“+”操作
//?替換加法運(yùn)算符?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 并迭代; 當(dāng) a == 0 (n < 4)時(shí),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))??
增強(qiáng)版:
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;?}?
第五種方法:使用內(nèi)聯(lián)匯編
#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;?}?
替換掉上面算法的++運(yùn)算符:
unsigned?inc(unsigned?x)?{???for?(unsigned?mask?=?1;?mask;?mask?<<=?1)?{?????if?(mask?&?x)???????x?&=?~mask;?????else???????return?x?&?mask;???}???return?0;?}?
這個(gè)版本更快一些:
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;?}?
第八種方法:實(shí)現(xiàn)乘法
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);?}?
原理:
因?yàn)?#xff0c; 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#實(shí)現(xiàn),因?yàn)樽髡吒煜#,但本題更傾向于算法,所以語(yǔ)言并不是太重要吧?(當(dāng)然只是在不使用語(yǔ)言特性的前提下。)
如果你還想了解更多的方法可以點(diǎn)擊這里。
總結(jié)
以上是生活随笔為你收集整理的[算法]不使用*、/、+、-、%操作符求一个数的1/3的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。