综合以上所述,对上面两种数据结构取长补短:用字符串读入数据,用数组存储数据。
2.
运算过程:
(1)
运算顺序
:两个数靠右对齐;从低位向高位运算;先计算低位再计算高位;
(2)运算规则:同一位的两个数相加再加上从低位来的进位,成为该位的和;这个和去掉向高位的进位就成为该位的值;如上例:3+8+1=12,向前一位进1,本位的值是2;可借助MOD、DIV运算完成这一步;
(3)最后一位的进位:如果完成两个数的相加后,进位位值不为0,则应添加一位;
(4)如果两个加数位数不一样多,则按位数多的一个进行计算。
3. 结果的输出(这也是优化的一个重点):
按运算结果的实际位数输出4.
优化:
(1)浪费空间:一个整型变量(-32768~32767)只存放一位(0~9);
(2)浪费时间:一次加减只处理一位;
之前写的高精度加法计算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)
{
unsigned char arr1[MAX]={0},arr2[MAX]={0};
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。