面试官让你用C语言实现大数相乘,慌吗?
在之前的筆試題解析里面,我寫了大數相加的問題,這里再剖析一個大數相乘,顧名思義,大數相乘就是這個數已經大到最大的數據類型都沒有辦法保存了。
我們看看最大的數據類型可以保存多大的數據。
#include?"stdio.h" #include?"string.h" int?main() {printf("0~%llu\n",(1ULL?<<?sizeof(unsigned?long?long)*8)?-1);return?0; }代碼輸出:
0~18446744073709551615所以如果我們的數大于18446744073709551615 就會存在沒有一個數據類型可以存儲的情況,所以會有大數相乘的問題。
如何解決大數相乘問題?
看我下面的解題思路,這個思路可以也是從網上看到的。
我們拿乘數的最低位,也就是2358 中的8 依次乘以被乘數的每一位,然后不做進位處理得到8 16 32 40.
繼續拿十位,百位,千位相乘,還是不進位
然后依次列相加,相加的時候,也不做進位處理得到一個數據2 7 19 40 51 57 40.
后面循環對上一步得到的數據進行進位處理,就會得到最終的結果。
代碼實現
#include?"stdio.h" #include?"string.h"#define?char_to_int(a)?(int)?(a?-?'0') #define?int_to_char(a)?(char)(a?+?'0')int?main() {char?a[1000]={"1245"};char?b[1000]={"2358"};char?c[1000]={0};int?i?=?0,?j?=?0,?k?=?0;memset(c,0,sizeof(c));printf("%ld\n",strlen(a)-1);printf("%ld\n",strlen(b)-1);/*完成圖片中的1,2步,結果從數組開頭開始存放*/for?(i?=?0;?i<strlen(a);?i++){k?=?i;for?(j?=?0;?j<strlen(b);?j++){c[k]?+=?char_to_int(a[i])?*?char_to_int(b[j]);k++;}}printf("k=%d?\n%.2d?%.2d?%.2d?%.2d?%.2d?%.2d?%.2d\n",k,c[0],c[1],c[2],c[3],c[4],c[5],c[6]);/*完成圖片中的3步,從后面往前面*/for?(i?=?k-1;?i>0;?i--){if?(c[i]?>=?10)?{c[i-1]?=?c[i]/10?+?c[i-1];c[i]?=?c[i]%10;printf("%.2d?%.2d?%.2d?%.2d?%.2d?%.2d?%.2d\n",c[0],c[1],c[2],c[3],c[4],c[5],c[6]);}}/*輸出*/for(i=0;i<k;i++)printf("%d",c[i]);putchar('\n');return?0; }我這個代碼直接參照我上面的圖片例程編寫,比較有參考性,大家在看代碼的時候也需要注意一些細節,比如strlen獲取的長度,k變量的大小等等。
程序輸出:
3 3 k=7 02 07 19 40 51 57 40 02 07 19 40 51 61 00 02 07 19 40 57 01 00 02 07 19 45 07 01 00 02 07 23 05 07 01 00 02 09 03 05 07 01 00 2935710隨機驗證下代碼
驗證的時候發現上面寫的代碼還有一些問題,順便修改了下
#include?"stdio.h" #include?"string.h"#define?char_to_int(a)?(int)?(a?-?'0') #define?int_to_char(a)?(char)(a?+?'0')int?main() {char?a[1000]={"1561591985156415641419841516515919"};char?b[1000]={"45645689129812561564159129821985125641"};unsigned?long?long?c[1000]={0};int?i?=?0,?j?=?0,?k?=?0;memset(c,0,sizeof(c));/*完成圖片中的1,2步,結果從數組開頭開始存放*/for?(i?=?0;?i<strlen(a);?i++){k?=?i;for?(j?=?0;?j<strlen(b);?j++){c[k]?+=?char_to_int(a[i])?*?char_to_int(b[j]);k++;}}/*完成圖片中的3步,從后面往前面*/for?(i?=?k-1;?i>0;?i--){if?(c[i]?>=?10)?{c[i-1]?=?c[i]/10?+?c[i-1];c[i]?=?c[i]%10;}}/*輸出*/for(i=0;i<k;i++)printf("%llu",c[i]);putchar('\n');return?0; }代碼輸出:
71279942302056620434200279768171066840415273983925010258196655791579079但是遺憾的是,電腦自帶的計算器不能計算這么大的數據,所以,我也不知道這個計算結果是不是正確的。
所以計算一個計算器可以計算的值
#include?"stdio.h" #include?"string.h"#define?char_to_int(a)?(int)?(a?-?'0') #define?int_to_char(a)?(char)(a?+?'0')int?main() {char?a[1000]={"1844674407"};char?b[1000]={"3709551615"};unsigned?long?long?c[1000]={0};int?i?=?0,?j?=?0,?k?=?0;memset(c,0,sizeof(c));/*完成圖片中的1,2步,結果從數組開頭開始存放*/for?(i?=?0;?i<strlen(a);?i++){k?=?i;for?(j?=?0;?j<strlen(b);?j++){c[k]?+=?char_to_int(a[i])?*?char_to_int(b[j]);k++;}}/*完成圖片中的3步,從后面往前面*/for?(i?=?k-1;?i>0;?i--){if?(c[i]?>=?10)?{c[i-1]?=?c[i]/10?+?c[i-1];c[i]?=?c[i]%10;}}/*輸出*/for(i=0;i<k;i++)printf("%llu",c[i]);putchar('\n');return?0; }程序輸出:
6842914925636017305計算器輸出
好吧,再來一次
#include?"stdio.h" #include?"string.h"#define?char_to_int(a)?(int)?(a?-?'0') #define?int_to_char(a)?(char)(a?+?'0')int?main() {char?a[1000]={"184467"};char?b[1000]={"3709551615"};unsigned?long?long?c[1000]={0};int?i?=?0,?j?=?0,?k?=?0;memset(c,0,sizeof(c));/*完成圖片中的1,2步,結果從數組開頭開始存放*/for?(i?=?0;?i<strlen(a);?i++){k?=?i;for?(j?=?0;?j<strlen(b);?j++){c[k]?+=?char_to_int(a[i])?*?char_to_int(b[j]);k++;}}/*完成圖片中的3步,從后面往前面*/for?(i?=?k-1;?i>0;?i--){if?(c[i]?>=?10)?{c[i-1]?=?c[i]/10?+?c[i-1];c[i]?=?c[i]%10;}}/*輸出*/for(i=0;i<k;i++)printf("%llu",c[i]);putchar('\n');return?0; }程序輸出
684289857764205計算器輸出
嗯,好像沒有問題。
其他的大數相乘算法
我上面的代碼不是最優解,但是可以讓大家理解這個過程,如果想了解比較優秀的解決方案,可以網上找找資料。
https://en.wikipedia.org/wiki/Sch%C3%B6nhage%E2%80%93Strassen_algorithmhttps://blog.csdn.net/u010983881/article/details/77503519推薦閱讀:
專輯|Linux文章匯總
專輯|程序人生
專輯|C語言
我的知識小密圈
關注公眾號,后臺回復「1024」獲取學習資料網盤鏈接。
歡迎點贊,關注,轉發,在看,您的每一次鼓勵,我都將銘記于心~
嵌入式Linux
微信掃描二維碼,關注我的公眾號
總結
以上是生活随笔為你收集整理的面试官让你用C语言实现大数相乘,慌吗?的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Linus 在圣诞节想提前放假做了这些解
- 下一篇: SqlServer数据库(可疑)解决办法