C語言 高精度演算法

2021-06-23 06:30:50 字數 4349 閱讀 7439

筆者去年總結了pascal裡有關高精度計算的問題,首先高精度計算可以解決以下四個問題:

1. 加數,減數,

運算結果的輸入和儲存:

運算因子超出了整型、實型能表示的範圍,肯定不能直接用乙個數的形式來表示。

在pascal中,能表示多個數的資料型別有兩種:陣列和字串。

陣列:每個陣列元素儲存1位(在優化時,這裡是乙個重點!),有多少位就需要多少個陣列元素;用陣列表示數的優點:每一位都是數的形式,可以直接加減;運算時非常方便。用陣列表示數的缺點:陣列不能直接輸入;輸入時每兩位數之間必須有分隔符,不符合數值的輸入習慣;

字串:string型字串的最大長度是255,可以表示255位。ansistring型字串長度不受限制。用字串表示數的優點:能直接輸入輸出,輸入時,每兩位數之間不必分隔符,符合數值的輸入習慣;用字串表示數的缺點:字串中的每一位是乙個字元,不能直接進行運算,必須先將它轉化為數值再進行運算;運算時非常不方便;

綜合以上所述,對上面兩種資料結構取長補短:用字串讀入資料,用陣列儲存資料。

2. 運算過程:

(1)運算順序

:兩個數靠右對齊;從低位向高位運算;先計算低位再計算高位;

(2)運算規則:同一位的兩個數相加再加上從低位來的進製,成為該位的和;這個和去掉向高位的進製就成為該位的值;如上例:3+8+1=12,向前一位進1,本位的值是2;可借助mod、div運算完成這一步;

(3)最後一位的進製:如果完成兩個數的相加後,進製位值不為0,則應新增一位;

(4)如果兩個加數字數不一樣多,則按位數多的乙個進行計算。

3. 結果的輸出(這也是優化的乙個重點):

按運算結果的實際位數輸出

4.

優化:

(1)浪費空間:乙個整型變數(-32768~32767)只存放一位(0~9);

之前寫的高精度加法計算pascal**如下:(可以根據上面高精度計算能解決的四個問題來理解)

program test;

type

my_arr=array [0..100] of longint;

var

str1,str2:string;

d1,d2,d3:my_arr;

procedure replace(str:string;var arr:my_arr);

var

i,j:longint;

begin

arr[0]:=length(str);

for i:=1 to arr[0] do

begin

arr[i]:=ord(str[arr[0]-i+1])-ord('0');

end;

end;

function max(i,j:longint):longint;

begin

if i>j then exit(i);

exit(j);

end;

procedure add_arr(arr1,arr2:my_arr;var arr3:my_arr);

var

i,j,k,t:longint;

begin

fillchar(arr3,sizeof(arr3),0);

k:=max(arr1[0],arr2[0]);

for i:=1 to k do

begin

t:=(arr1[i]+arr2[i]+arr3[i]);

arr3[i]:=t mod 10;

arr3[i+1]:=t div 10;

end;

if arr3[k+1]<>0 then

arr3[0]:=k+1

else

arr3[0]:=k;

end;

procedure print_arr(arr:my_arr);

var

i:longint;

begin

if arr[0]=0 then

begin

writeln(0);

exit;

end;

for i:=arr[0] downto 1 do

write(arr[i]);

writeln;

end;

begin

readln(str1);

replace(str1,d1);

readln(str2);

replace(str2,d2);

add_arr(d1,d2,d3);

print_arr(d3);

end.

筆者大一的時候學了一種新的程式語言叫做c語言,相信很多同學都已經接觸過c語言了,今天在xiaoz吧看到某無良吧主發的題目,我就說這題目不是一般a+b,這傢伙還一直狡辯,現在我來跟大家分享一下有關高精度計算的c語言演算法。

不多說,當然先上無良吧主今日分享的題目,見下圖:

首先我來分析一下這道題目,這道題目的case2:112233445566778899+998877665544332211=1111111111111111110,看到這個數字很多同學就開始想了,我能不能用long int或者double型呢?

double 變數以帶符號的 ieee 64 位(8 個位元組)雙精度浮點數形式儲存,負值取值範圍為 -1.79769313486231570e+308 到 -4.94065645841246544e-324,正值取值範圍為 4.94065645841246544e-324 到 1.79769313486231570e+308。

long int 的取值範圍為 

-2147483648至2147483647,很顯然,是不能用long int的,如果使用long int,則資料溢位。

如果使用double型,則運算速率會非常慢。大家可以試試。最好讓無良的吧主去試試。煩死他!

ok,現在,我來說說這道題目的正確演算法。這道題目明顯就是必須要用高精度計算。

因為是任意長的二整數求和,而系統中整型數的精度有限,因此需用字串形式儲存整數,並按位逐

位進行運算,運算過程中需考慮進製和借位的問題。再者,整數可以是負數,若二整數符號相同則為加法運

算,相異則實為減法運算,若是減法運算還需比較二數的絕對值大小,以確定最終結果的符號及減數與被

減數的安排順序。

無良吧主出的出的拿到題目正確演算法如下:(大家可以任意輸入數字檢驗)

#include#include#define max 1000                               /*巨集定義,下面遇到max的時候都變成1000 */

int main(void)

,arr2[max]=;

int len,i,len1,len2,t,j = 0;

char str[max]; /*讀入資料,並進行預處理(計算出數字位數,並反方向存放)*/

scanf("%s",str);

len1 = strlen(str);

for(i=0; ilen2)?len1:len2;

for(i=0; i演算法的思路:

模擬我們在小學所學的筆算

(對於不足位用0補齊,如9818+13,我們認為是9818+0013),

假設我們要計算的兩數分別是 a1 a2 a3 a4 、 b1 b2 b3 b4。

那麼我們筆算時,會列出這樣的式子

a1  a2  a3  a4

+b1  b2  b3  b4

---------------------

c0  c1 c2 c3 c4

那麼我們在計算機中也同樣可以完成這個過程。為了方便進製,我們在計算前,將兩個數反向儲存至陣列中,即我們是對  b4 b3 b2 b1 、a4 a3 a2 a1 進行計算。

初始化時 j = 0,

其中有恒等式   cn  = (an + bn + j)mod  10  (j為進製結果),

根據這個等式我們只需要迴圈執行以下三步,就能得到大致結果:

1.

temp = an + bn +j

2.

cn = temp mod 10

3. j

= temp div 10

迴圈完成後,我們還需要進行最後一步,因為兩個最高位相加仍可能產生進製,所以,我們在這裡還要額外做一次對 j 的判斷,如果 j 值為 1 的話, cn+1 應該要進製,即 cn+1 = 1。

基礎 (C語言)高精度演算法

三 總結 多數時候我們需要進行非常龐大的數字運算,其中涉及四則運算,加減乘除,但是當連最大的long long型別也容納不下如此大的數字的時候,我們應該怎麼辦?那麼,我們就要用到今天所介紹的高精度演算法,顧名思義,我們可以用一些特殊的方式來得出我們想要計算的答案。在講高精度演算法之前,我們需要引入陣...

(C語言)高精度加法

我們知道 int 和 long 型別的變數在64位作業系統中能表示的資料範圍為 2 31,2 31 1 long long 型別的變數能表示的資料範圍為 2 63,2 63 1 但是現在我們需要計算的資料超過了long long 型資料能表示的範圍。這時候我們就需要使用高進度演算法。什麼是高精度演算...

C語言 高精度加法

問題描述 輸入兩個整數 a和b,輸出這兩個整數的和。a和b都不超過100位。演算法描述 由於 a和b都比較大,所以不能直接使用語言中的標準資料型別來儲存。對於這種問題,一般使用陣列來處理。定義乙個陣列 a,a 0 用於儲存 a的個位,a 1 用於儲存 a的十位,依此類推。同樣可以用乙個陣列 b來儲存...