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

摘要:算法一直是程序員進階的一道龍門,通常算法都是為了更高效地解決問題而創造的,但也有的只是出于學術性,并不在意其實際意義。這是近日在國外技術問答網站stackoverflow的一個熱門問題,不知道你能給出幾種解決方法?

導讀:算法一直是程序員進階的一道龍門,通常算法都是為了更高效地解決問題而創造的,但也有的只是出于學術性,并不在意其實際意義。這是近日在國外技術問答網站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. ?
  13. int?divideby3?(int?num)?{?
  14. ????int?sum?=?0;?
  15. ????while?(num?>?3)?{?
  16. ????????sum?=?add(num?>>?2,?sum);?
  17. ????????num?=?add(num?>>?2,?num?&?3);?
  18. ????}?
  19. ????if?(num?==?3)?
  20. ????????sum?=?add(sum,?1);?
  21. ????return?sum;??
  22. }?

原理: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. {?
  5. ????FILE?*?fp=fopen("temp.dat","w+b");?
  6. ????int?number=12346;?
  7. ????int?divisor=3;?
  8. ????char?*?buf?=?calloc(number,1);?
  9. ????fwrite(buf,number,1,fp);?
  10. ????rewind(fp);?
  11. ????int?result=fread(buf,divisor,number,fp);?
  12. ????printf("%d?/?%d?=?%d",?number,?divisor,?result);?
  13. ????free(buf);?
  14. ????fclose(fp);?
  15. ????return?0;?
  16. }?

第三種方法:

  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. {?
  5. ????int?num?=?1234567;?
  6. ????int?den?=?3;?
  7. ????div_t?r?=?div(num,den);?//?div()是標準C語言函數
  8. ????printf("%d\n",?r.quot);?
  9. ????return?0;?
  10. }?

第五種方法:使用內聯匯編

  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);?
  15. }?

第六種方法:

  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?
  10. }?

第七種方法:

  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;?
  10. }?

替換掉上面算法的++運算符:

  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)
  9. }?

這個版本更快一些:

  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. ?
  6. unsigned?div_by(unsigned?const?x,?unsigned?const?by)?{?
  7. ??unsigned?floor?=?0;?
  8. ??for?(unsigned?cmp?=?0,?r?=?0;?cmp?<=?x;)?{?
  9. ????cmp?=?add(0,cmp,by);?
  10. ????floor?=?r;?
  11. ????r?=?add(0,r,1);?
  12. ??}?
  13. ??return?floor;?
  14. }?

第八種方法:實現乘法

  1. int?mul(int?const?x,?int?const?y)?{?
  2. ??return?sizeof(struct?{?
  3. ????char?const?ignore[y];?
  4. ??}[x]);?
  5. }?

第九種方法:極限

  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. ?
  9. public?static?long?add(long?a,?long?b)?{?
  10. ????long?carry?=?(a?&?b)?<<?1;?
  11. ????long?sum?=?(a?^?b);?
  12. ????return?carry?==?0???sum?:?add(carry,?sum);?
  13. }?

原理:

因為, 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. }?
  19. public?static?int?Negate(int?a)?{?
  20. ????return?Add(~a,?1);?
  21. }?
  22. public?static?int?Add(int?a,?int?b)?{?
  23. ????int?x?=?0;?
  24. ????x?=?a?^?b;?
  25. ????while?((a?&?b)?!=?0)?{?
  26. ????????b?=?(a?&?b)?<<?1;?
  27. ????????a?=?x;?
  28. ????????x?=?a?^?b;?
  29. ????}?
  30. ????return?x;?
  31. }?

注:本例是C#實現,因為作者更熟悉C#,但本題更傾向于算法,所以語言并不是太重要吧?(當然只是在不使用語言特性的前提下。)

如果你還想了解更多的方法可以點擊這里。


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/450802.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/450802.shtml
英文地址,請注明出處:http://en.pswp.cn/news/450802.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

2022屆互聯網秋招備戰

文章目錄1、何為秋招&#xff1f;1.1應屆生身份1.2秋招、春招、校招1.3、社招、海投2.秋招信息如何獲取&#xff1f;3、如何備戰秋招&#xff1f;3.1、簡歷&#xff08;ps做簡歷&#xff09;3.2、筆試準備3.3、面試準備4、日常實習和暑假實習&#xff1f;1、春招≠暑期實習2、什…

php 兩變量值互換 方法

//方法一&#xff1a;$a "abc";$b"def";$a $a^$b;$b $b^$a;$a $a^$b;//方法二&#xff1a;list($a, $b) array($b, $a);//方法三&#xff1a;$a $a . $b;$b strlen( $b );$b substr( $a,0,(strlen($a)- $b ));$a substr( $a, strlen($b));//方法四&…

MySQL5.7 group by新特性,報錯1055

項目中本來使用的是mysql5.6進行開發&#xff0c;切換到5.7之后&#xff0c;突然發現原來的一些sql運行都報錯&#xff0c;錯誤編碼1055&#xff0c;錯誤信息和sql_mode中的“only_full_group_by“關&#xff0c;到網上看了原因&#xff0c;說是mysql5.7中only_full_group_by這…

IDEA中多行注釋及取消注釋快捷鍵

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 1、一次性添加多行注釋的快捷鍵 首先選中要注釋區域&#xff0c;然后 ctrl/ 這個是多行代碼分行注釋&#xff0c;每行一個注釋…

為什么程序員不擅長估算時間?

摘要&#xff1a;時間估算是困難的&#xff0c;每一個程序員都有一個現實的估計區間&#xff0c;低于這個區間的估計意味著&#xff08;構件&#xff0c;測試&#xff0c;檢查代碼的&#xff09;時間開銷被低估了&#xff0c;超過這個區間的估計意味著這個任務太大而很難預估。…

red hat enterprise linux 7關閉防火墻的方法

2019獨角獸企業重金招聘Python工程師標準>>> red hat enterprise linux 7發布后&#xff0c;發現防火墻也變了&#xff0c;如何關閉防火墻呢&#xff0c;下面是方法 1.查看firewall的狀態 [rootsztech7 ~]# systemctl status firewalld firewalld.service - firewal…

IOS —— 網絡那些事(上) - http協議

作為一名并不太合格的程序員&#xff0c;今天要分享學習的成果&#xff0c;竟然講的是網絡相關HTTP協議的事情。&#xff08;也算是復習了&#xff09; 乍看HTTP協議的內容著實是十分復雜的&#xff0c;涉及到十分多互聯網"底層"框架的東西。今天就先撇開這部分詳細內…

【最新版】Java速成路線(急于找工作!)

文章目錄計算機網絡分層結構TCP/UDPHTTP/HTTPS狀態碼Cookie 和 SessionURI和URL操作系統線程和進程數據結構和算法數據結構算法設計模式&#xff08;23種&#xff09;單例工廠代理適配器觀察者模板實操工具Git/SVNMaven/GradleLinux基本操作NginxELKpostmanJAVA基礎語言基礎JVM…

Java Web Start實例

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 JWS讓用戶可以下載服務器端的Java Application到本機運行&#xff0c;并且沒有安裝、配置等繁瑣的操作JWS的運行原理&#xff1a;瀏覽器…

老派程序員——徒手實現偉大成就

摘要&#xff1a;本文介紹了三位非常著名的程序員&#xff1a;Ken Thompson,Joe Armstrong 和 Jamie Zawinski&#xff0c;他們是如何發明一門新語言&#xff0c;他們開發軟件時會像我們一樣使用當今流行的開發工具嗎&#xff1f;當讀Peter Seibel的精彩著作《編程人生:15位軟件…

互聯網大廠項目研發流程

文章目錄階段一&#xff1a;階段二&#xff1a;階段三&#xff1a;階段四&#xff1a;階段五&#xff1a;開發人員&#xff1a;測試人員&#xff1a;設計師&#xff1a;階段六&#xff1a;階段七&#xff1a;總結&#xff1a;本文章學習自&#xff1a;https://www.bilibili.com…

centos常見錯誤 Failed to set locale, defaulting to C

錯誤描述&#xff1a; 當在centos中使用yum命令時&#xff0c;輸出錯誤&#xff1a; [rootlocalhost yum.repos.d]# yum list |grep prceFailed to set locale, defaulting to C 用locale檢測&#xff0c;出現如下提示&#xff1a; rootlocalhost yum.repos.d]# localelocale: …

圖片上傳知識點梳理

在日常項目開發中&#xff0c;圖片上傳是一個十分常見的場景。而現在的各種UI框架都提供了自己的上傳組件&#xff0c;網上第三方的上傳組件也多如牛毛。可能你早已習慣了直接使用這些現成的組件&#xff0c;然而對于其具體的實現&#xff0c;卻并未深入解析。本文將通過簡單的…

解決 java.lang.IllegalArgumentException: Repository interface must not be null on initialization!

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 報錯&#xff1a;Caused by: java.lang.IllegalArgumentException: Repository interface must not be null on initialization! Cause…

【狂神說】JVM

文章目錄1.JVM的位置2.JVM的體系結構3.類加載器4.雙親委派機制&#xff08;重要&#xff09;5.沙箱安全機制(了解)6.native&#xff08;核心&#xff09;7.PC寄存器&#xff08;了解&#xff09;8.方法區9.棧10.三種JVM11.堆&#xff08;Heap&#xff09;12.新生區、老年區13.永…

我們真的需要統一的編程規范?

摘要&#xff1a;仁者見仁智者見智&#xff0c;編碼風格的不同&#xff0c;對項目也會有不同的影響&#xff0c;統一的編碼規范有益于項目的維護。俗話說&#xff0c;沒有規矩不成方圓&#xff0c;在2004年&#xff0c;UNIX創始人之一的Ken Arnold就發表了一篇很幽默文章&#…

百度云重磅發布ABC 3.0 尹世明如何詮釋百度云的“新”打法

雷鋒網9月4日消息&#xff0c;2018百度云智峰會正式召開&#xff0c;百度總裁張亞勤發表題為《新技術驅動&#xff0c;全面進入Cloud2.0》的演講并表示&#xff0c;經歷了PCClient/Server到MobileCloud 1.0&#xff0c;再到如今的AICloud 2.0過程&#xff0c;新技術推動云計算產…

EcmaScript對象克隆之謎

先談談深拷貝 如何在js中獲得一個克隆對象&#xff0c;可以說是喜聞樂見的話題了。相信大家都了解引用類型與基本類型&#xff0c;也都知道有種叫做深拷貝的東西&#xff0c;傳說深拷貝可以獲得一個克隆對象&#xff01;那么像我這樣的萌新自然就去學習了一波&#xff0c;我們能…

開發人員眼中最好的代碼編輯器是誰?

摘要&#xff1a;對開發人員來講&#xff0c;開發工具就好比戰場上的“兵器”&#xff0c;不同領域的開發人員他們所使用的“兵器”也不完全相同&#xff0c;本文從友好性、功能性、擴展等多方面總結了最受開發人員歡迎的“兵器”。你最愛的那個在這里嗎&#xff1f; 如果我們把…

關于RESTful一些注意事項,接口開發規范

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 最近在研究restful&#xff0c;公司開發要使用&#xff0c;所以自己就去網上找了好些資料&#xff0c;并整理了一套公司開發的接口規范。…