level 13
就是用数组表示数,如11就用a【1】=1,a[2]=1来表示。当相加减乘时做相应的改动,如55+85,就设a[1]=5,a[2]=5,b[1]=8,b[2]=5,a[2]+b[2]=10就设c[2]=0,c[1]=1,a[1]+b[1]=13,所以c[1]=1+3=4.由于有进位,我个人习惯把整串数往后移一格,即c[3]=0,c[2]=4,c[1]=1,即55+85=140
2013年11月08日 14点11分
6
level 8
这是算阶乘,然后乘2的一个程序
var i,j,n:longint;
c:array[1..1500] of longint;
procedure jw; // 这是高精度进位用的函数
var i,k:longint;
begin
for i:=1 to 1499 do if c[i]>9 then begin
k:=c[i] div 10;
c[i]:=c[i] mod 10;
c[i+1]:=c[i+1]+k;
end;
end;
begin
assign(input,'gl.in');reset(input); //头两行和最后一行是文件操作,不用管
assign(output,'gl.out');rewrite(output);
readln(n);
c[1]:=1; //设定初始值
for i:=2 to n do begin //循环
for j:=1 to 1500 do c[j]:=c[j]*i; //所有位数全部乘以当前阶乘乘到的数
jw; // 进位
end;
for i:=1 to 1500 do c[i]:=c[i]*2; // 全部乘2
jw; //进位
for i:=1500 downto 1 do if c[i]>0 then break; //寻找数的最高位
for j:=i downto 1 do write(c[j]); //从最高位开始向下输出
close(input);close(output);
end.
基础高精度每次操作后都要进位,有改良版的,但那就比较复杂了。
2013年11月09日 03点11分
7
level 9
坦白说,高精度不是中学生能玩的。这里只是简单的说说实现超长整数的要点。
数据结构方面可以用一个数组代表一个非负整数(高端一点的可以包括负整数,即是说再加一个整数以记其正负号),其元素分别对应这个整数的的每个位数。位数的储存次序,以由低位至高位的储存方式较为方便编程工作。
算法的设计可以参考中小学生的算术课本,没有任何特别之处。
一些设计的注意事项:
1)尽管代表的数可以很大,在操作中仍然有溢位之可能。因此,函数要有传回值以便回传错误码。
2)函数的某些参数有可能是相同的位址,因此要设计无误的程式码,要注意读取变数和更改变数的次序问题(另外,如果有些参数根本上不容许是相同的位址,要回传错误码)。更改变数甲后,再读取变数乙,可能会出现问题,因为变数甲和变数乙可能同一位置。因此,要从根本上防止这个问题的出现,比较有系统而乾净的解决方案是,先把源参数抄写到暂时变数,得到结果后再抄写到目的地变数。
3)完成编程后要多加测试,确保结果是正确的。
4)中小学生的乘除算法在计算机上的执行速度会比加减慢很多。位数大概不能超过数千(十进制),否则花时会过长。
2013年11月09日 17点11分
9
额外提示: 1)内部表示法用一万或一百进制(分别为二或一字节阵列)比较便利除错工作,空间利用率不算太低。 2)除法可以不按照相同的进制去计算。在概念上,先顺序取得商数的二进制(或其他进制)表示法的每个位数,再转换成内部使用的的进制。在实作中,两者同时进行就不需占用额外的记忆空间。
2013年11月10日 18点11分
比如m是最大的正整数数使得pow(2,m)*除数=2^m*除数不致於过大,仍然可以内部表示,二进制除法伪代码如下 r := 被除数; q := 0; for n := m downto 0 do begin if pow(2, n)*除数 >= r then begin r := r - pow(2, n)*除数; q := q + pow(2, n); end; end;
2013年11月10日 18点11分
关於溢位的问题补充两点。 第一,在一般运算中几乎不可能超出袋装科学计算机的表示范围,因此用一个一百位元组的阵列(一百进制)已远超所需。如果这样都溢位的话,几乎可以肯定是运算程序出错。 第二,可以考虑留一位置标记是否已发生溢位(及总位数?)。如果是,阵列数据不可靠,不可使用。
2013年11月14日 09点11分