大數運算#

在這里插入圖片描述
?大數,就是C/C++中利用基本類型所不能存儲的數字,少則數十位,大則幾萬位,如何存儲和計算大數就是本文的內容。

?在C和C++中,沒有存儲大數的數據結構,就算 unsigned long long也只能表示19位的數字
在這里插入圖片描述
?如果我們用double則會出現精度不準確的問題,如果我們想精確儲存計算大數,學習本文是必要的。
?存儲大數的方法有兩種,不管是數組還是字符串,在運算時他們的原理其實是相同的。
看下邊兩道題,帶你了解大數的計算方法

字符串相加
在這里插入圖片描述
在這里插入圖片描述
?這道題的思路很簡單,不能將字符串轉換為整數形式,就算轉了我們也過不了這道題。因為數據的范圍很大。
在這里插入圖片描述
?長度為一萬的數字字符串,這就是一個很大的數了。
?解決思路:還記得我們小學時是如何進行加法運算的嗎?我們從地位算起,如果兩個加數和大于10,我們就會進一,按照這種思路依次進行計算,知道求出結果為止。
在這里插入圖片描述
通過這種思路我們可以寫出這樣的代碼

class Solution {
public:string addStrings(string num1, string num2) {int i = num1.length() - 1, j = num2.length() - 1, add = 0;string ans = "";while (i >= 0 || j >= 0) {int x = i >= 0 ? num1[i] - '0' : 0;int y = j >= 0 ? num2[j] - '0' : 0;int result = x + y + add;ans.insert(ans.begin(),'0' + result % 10);add = result / 10;i -= 1;j -= 1;}return ans;}
};

?可以看出,計算時是從字符串末尾一次項前進行求和計算。如果該數大于10,就會將進位更新為1,改為的結果直接將相加后的值模上10的計算結果頭插進去即可。
在這里插入圖片描述

?三目運算符十分巧妙,在求和時,要一直將兩數組的元素全部加一遍,如果短的數組已經加完就作為0,這樣也不會出現越界訪問,還解決了要判斷是哪個數組更短的問題,統一對待。在每次對應位計算完成之后更新add(進位數)。然后繼續加進位的數字。
信心滿滿提交
在這里插入圖片描述
?最后一次進位的情況被我們忽略了,就像上邊的錯誤用例一樣。所以當i和j全部減到零,并且進位add也等于0時循環結束。

class Solution {
public:string addStrings(string num1, string num2) {int i = num1.length() - 1, j = num2.length() - 1, add = 0;string ans = "";while (i >= 0 || j >= 0 || add != 0) {int x = i >= 0 ? num1[i] - '0' : 0;int y = j >= 0 ? num2[j] - '0' : 0;int result = x + y + add;//該位置上兩個數字求和結果ans.insert(ans.begin(),'0' + result % 10);add = result / 10;i -= 1;//向前一位進發j -= 1;}return ans;}
};

這道題就完成了。
就算兩個字符串很長很長,計算也很快,結果也是準確的。
在這里插入圖片描述

用數組進行存儲運算

?用數組存儲的話,要保證數組中任意元素不大于10,這才是無誤的存儲方法,如果某個元素大于10,那就全亂了,一般請況下我們都是用數組進行存儲大數操作,而不是計算。就算是要計算的話還要給你提供每個元素都是小于10的數字,用上邊字符串的思路進行計算就可以了。

存儲大數,一般是通過數組保存運算后很大的數字。
例如求某數的階乘
在這里插入圖片描述
100的階乘long long就已經受不了了,那么如何進行精確計算呢?
還是回憶小學時候我們如何計算乘法的呢?
在這里插入圖片描述
?上邊的字符串相加的題目中,我們可以發現進位add只有兩種,0或者1,因為就算兩個9相加,結果也還是18,進位仍然是1,在這里就不同了。
?我們可以把99*99看做在數組中保存的兩個9分別乘以99,他們在數組中的位置表示他們的位數。
在這里插入圖片描述
?如果是求階乘的話,就是要將兩個數字相乘之后的數字再乘以一個數而已,同樣的思路,多了一層循環。
?就像上邊,再乘以98的話,就是數組中每一位的數字都乘以98,然后重復上邊的操作就可以了。在乘以下一個數之前,要知道上一次乘完的結果的位數,起始時可以將計算的第一個數字乘以1,然后判斷出位數,再次運算時就使數組中每一位的數字乘以要乘以的數字。
?例如100的階乘,讓數組中首元素為1,第一次運算完成之后數組中前三個元素就是0,0,1,有三位數字,位數為cout=3。然后乘以99,就是數組中前三個元素乘以99,前兩個數字不變,最后的數字是大于10的,在進位結束后,判斷數組下標為2(一共3位數字,最后一位下標為2)的位置是否大于10,如果大于就進位,此時需要進位一個9,同時位數cout加1,當然,這是一個循環,如果最后一位乘的數不是99而是101,就要進位兩次,第一次進位10,第二次進位1,當然位數就要加2。
有了上邊的思路就可以寫代碼了

int main()
{int num = 0;scanf("%d", &num);if (num == 0){printf("1");}int a[10000] = { 0 };a[0] = 1;int cout = 1;//分為三步處理for (int i = num; i > 0; i--){int j = 0;//cout是位數,將所有的位數都乘以i。for (; j < cout; j++){a[j] *= i;}//將每個位判斷一下,如果大于等于10,就向前進位for (int k = 0; k < cout; k++){if (a[k] >= 10){a[k + 1] += a[k] / 10;a[k] = a[k] % 10;}}//從最后一位進行判斷,找到新的位數for (int l = cout; a[l] >0; l++){cout++;a[l + 1] = a[l] / 10;a[l] = a[l] % 10;}		}for (int i = cout-1; i >0; i--)//從后向前遍歷打印{printf("%d ", a[i]);}return 0;
}

?在循環結束時的cout就是結果的位數,同是數組中存放的就是結果的逆序。我在里開的空間是10000,如果計算出的數位數更大的話可以擴寬數組大小。
?本文到這里就結束啦,有用的話留一個贊再走叭,如果你的慧眼金睛發現了問題,一定要說哦,我會虛心改正噠。

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

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

相關文章

乘法口訣表的C語言編程

#include "stdio.h"int main() {int i,j,q0;for(i 1;i < 10; i){for(j 1;j < 10;j){q i*j;printf("%d*%d%d\n",i,j,q);}}} 按照課本上的排列做出的優化 #include "stdio.h"int main() {int i,j;for(i 1;i < 10; i){for(j 1;j <…

打印100-200之間的素數

素數 是指除了1和它本身以外,不能被任何整數整除的數 例如17就是素數,因為它不能被2~16的任一整數整除。 #include "stdio.h"int main() {int i,j;for(i 100; i < 200; i){for(j 2;j < i-1;j){if(i%j 0)break;}if(j i)printf("%d\n",i);}} C語言…

判斷1000-2000之間的閏年(優化寫法)

閏年普通年&#xff08;不能被100整除的年份&#xff09;能被4整除的為閏年。&#xff08;如2004年就是閏年,1999年不是閏年&#xff09;&#xff1b;世紀年&#xff08;能被100整除的年份&#xff09;能被400整除的是閏年。(如2000年是閏年&#xff0c;1900年不是閏年)&#x…

四種方法實現數組交換

方法一&#xff1a; //該方法主要用邏輯運算將數組對應的每個元素進行交換&#xff0c;然后用for循環將整個數組元素進行交換#include<stdio.h>int main(){ int i,j,k;int A[10];int B[10];int C[10];printf("請輸入A數組的內容&#xff1a;\n");for(i0;i<1…

結構體變量初始化

// // main.c // C語言學習 #include <stdio.h> int main(int argc, const charchar * argv[]) { //定義結構體類型 struct Person { charchar *name; int age; double heigth; }; //初始化的4種方式 //1.定義的同時初始化 struct Person p1 {"z…

C語言的細小知識點整理

1、register修飾符暗示編譯程序相應的變量將被頻繁地使用&#xff0c;如果可能的話&#xff0c;應將其保存在CPU的寄存器中&#xff0c;以加快其存儲速度 2、static是某個特定函數的局部變量&#xff0c;即只能在定義該變量的函數內使用該變量 static int a 40; char …

二維數組初始化規則

二維數組初始化的形式為&#xff1a;數據類型 數組名[整常量表達式][ 整常量表達式]{ 初始化數據 }&#xff1b;在{ }中給出各數組元素的初值&#xff0c;各初值之間用逗號分開。把{ }中的初值依次賦給各數組元素。有如下幾種初始化方式&#xff1a;⑴ 分行進行初始化int a[2][…

linux之緩沖區

行緩沖。在這種情況下&#xff0c;當在輸入和輸出中遇到換行符時&#xff0c;標準I/O庫執行I/O操作。這允許我們一次輸出一個字符&#xff0c;但只有在寫了一行之后才進行實際I/O操作。當流涉及一個終端時&#xff0c;通常使用行緩沖。 第一個例子&#xff1a;&#xff08;he…

輸出一個整數的每一位(3種方法)

1.使用數組按個數輸入再按照個數輸出 int i, j, k, num, count;int a[10];printf("幾位數\n");scanf("%d", &k);for (i 1; i < k; i){scanf("%d", &a[i]);}for (i k; i > 1; i--){printf("%d\n", a[i]);} 2.使用遞歸…

linux之地址空間

程序&#xff1a;一組指令的有效集合。它是靜態的&#xff0c;不具有任何的運行意義。程序最終轉換為二進制文件。 進程&#xff1a;程序的執行就是進程。可以把它看成獨立的程序&#xff0c;在內存中有其對應的代碼空間和數據空間。一個進程所擁有的數據和代碼只屬于自己。進…

C語言操作符 進階 (常見錯誤及細節)

1.算術操作符- * / % % 只適用于整數類型運算&#xff0c;其余運算符也可用于浮點運算。2.移位操作符 左移&#xff1a;左邊丟棄&#xff0c;右邊補0&#xff1b; 右移&#xff1a;不同編譯器采取的移位方式不同&#xff0c;所有有了“右移”的程序不可移植1.邏輯移位&#xff…

輸出該數二進制表示中1的個數。求取十進制數字元素1的個數 (3種方法)

/* ***求取十進制數字元素1的個數 */int fun(int x) {int count 0;int i, j, k;/***方法2 負數不可計算&#xff0c;需要改進*/while (x ! 0){if (x & 1 1){count;}x x >> 1;}/****方法1*/while (x ! 0){x x&(x - 1);count;}return count; }int main() {in…

C語言隨機數生成超詳解

1.首先來看一段簡單的代碼 #define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> #include <time.h>int main(void) {int i;printf(" %6d\n", rand());system("pause"); }printf(" %6d\n", rand());sys…

可變參數列表

一個函數在不同的時候接受不同數目的參數。 stdarg宏可變參數列表是通過宏來實現的&#xff0c;這些宏定義于stdarg.h頭文件中。這個頭文件聲明了一個類型va_list和三個宏---va_start,va_arg,va_end。va_list用于聲明變量的類型。va_start準備訪問可變參數。va_arg用于訪問參數…

完成猜數字游戲 //C語言 猜數字游戲(編寫過程詳解)

int i, j, k;int num 0;/*生成隨機數字*/num rand();printf("%d\n", num); 選擇玩游戲還是退出 void play(int x) {printf("%d\n", x);printf("開始游戲"); } scanf("%d", &k);switch (k){case 1:play(num);case 2:break;} 循環…

靜態順序表

順序表是在計算機內存中以數組的形式保存的線性表&#xff0c;是指用一組地址連續的存儲單元依次存儲數據元素的線性結構。線性表采用順序存儲的方式存儲就稱之為順序表。順序表是將表中的結點依次存放在計算機內存中一組地址連續的存儲單元中。 順序表分為靜態存儲的順序表和動…

C語言 淺談可變參數

1.可變參數產生原因 首先來看一個簡單的例子。 int Add(int x, int y) {return x y; } int main() {int sum 0;sum Add(1, 2);//sum Add(1, 2, 3);//sum Add(1);system("pause");return 0; } 我們可以看到&#xff0c;對于這個代碼只可以計算兩個數的加法。 …

有兩個鏈表a,b,設結點包括學號,姓名。從a鏈表中刪去與b鏈表中有相同學號的那些結點。

#include <stdio.h> #include <string.h> #include <stdlib.h> typedef struct linknode { int num;char name[20];struct linknode *next; }node; node *creat() { node *h NULL,*s,*t;int d;int i 1; char name1[20];while(1) { printf("輸入第…

C語言模擬實現標準庫函數之strlen()

strlen() strlen所作的僅僅是一個計數器的工作&#xff0c;它從內存的某個位置 &#xff08;可以是字符串開頭&#xff0c;中間某個位置&#xff0c;甚至是某個不確定的內存區域&#xff09; 開始掃描&#xff0c;直到碰到第一個字符串結束符\0為止&#xff0c;然后返回計數…

C語言模擬實現標準庫函數之strcpy()

strcpy(dest,src) strcpy是一種C語言的標準庫函數&#xff0c;strcpy把從src地址開始且含有\0結束符的字符串復制到以dest開始的地址空間&#xff0c;返回值的類型為char*。 char * my_strcpy(char *str2, char *str1) {assert(*str2);assert(*str1);while(*str1!0){ *str2 …