筆者去年總結了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來儲存...