在Delphi中使用字符串提升UInt64限制

时间:2014-11-21 21:25:13

标签: delphi

我正在使用UInt64达到我的极限,我想知道是否有功能可以执行简单的操作选项,例如+/-等,只需要字符串,因为它们可以存储与您一样多的RAM ......(理论上)

例如我想计算

24758800785707605497982484480 + 363463464326426并将结果作为字符串。

我知道如何使用数字系统0123456789解决字符串问题,并逐字逐句地溢出下一个位置 - 这将耗费更多的力量,但我不介意这个问题...

我想有这种能力进行这样的计算,直到我的RAM爆炸(这将是真正的限制......)

是否有这样的功能已经做到了?

3 个答案:

答案 0 :(得分:2)

Delphi中的语言级别不支持任意大整数,但谷歌搜索中出现http://www.delphiforfun.org/programs/Library/big_integers.htm,这可以支持它们作为图书馆。

答案 1 :(得分:1)

在超级计算机上,其称为BCD数学(二进制编码的十进制)和RAM的每个半字节表示十进制数字[0..9] - 不是RAM的有效使用,但是大量计算花费的时间最少(即约3 mSecs乘以200万位数字。快速PC上的BCD仿真器需要5或6分钟。

我永远不需要添加大数字,但我会增加。实际上我迭代地调用这个例程来计算例如1000000阶乘(5,565,709百万个数字答案.Str6Product指的是它如何砍掉一对字符串数.s1和s2的实际长度限制大约是2 ^ 31。函数是受到“字符串可以容纳”的限制。无论那个限制是什么,我都没有到过那里。

// ============================================= =================================

function Str6Product(s1: string; s2: string): string;     //    6-13  5:15 PM

var
  so,snxt6          : string;
  z1,z3, i, j, k    : Cardinal;      // Cardinal is 32-bit unsigned
  x1,x3,xm      : Cardinal;
  countr            : Cardinal;
  a1, a2, a3        : array of  Int64;
  inum, icarry      : uInt64;        // uInt64 is 64-bit signed
begin

s1 := '00000'+s1;
s2 := '00000'+s2;
z1 := length(s1);                            // set size of Cardinal arrays
z3 := z1 div 6;
x1 := length(s2);                            // set size of Cardinal arrays
x3 := x1 div 6;

xm := max(x3,z3);
SetLength(a1,xm+1);                         
SetLength(a2,xm+1);                      

                                       // try to keep s1 and s2 about the 
                                       // same length for best performance
for i := 1 to xm do begin              // from rt 2 lft - fill arrays
                                       // with 4-byte integers
   if i <= z3 then a1[i]  := StrToInt(copy (s1, z1-i*6+1, 6));
   if i <= x3 then a2[i]  := StrToInt(copy (s2, x1-i*6+1, 6));
   if i  > z3 then a1[i]  := 0;
   if i  > x3 then a2[i]  := 0;
end;

k := max(xm-x3, xm-z3);                      // k prevents leading zeroes
SetLength(a3,xm+xm+1);

icarry := 0;     countr := 0;
icMax  := 0;     inMax  := 0;

for i := 1 to xm do begin             // begin 33 lines of "string mult" engine
   inum := 0;
   for j := 1 to i do
      inum := inum + (a1[i-j+1] * a2[j]);

   icarry := icarry + inum;
   if icMax < icarry then icMax := icarry;
   if inMax < inum   then inMax := inum;
   inum   := icarry mod 1000000;
   icarry := icarry div 1000000;
   countr := countr + 1;
   a3[countr] := inum;
end;
if xm > 1 then begin
   for i := xm  downto k+1 do begin                      // k or 2
      inum := 0;
      for j := 2 to i  do
         inum := inum + (a1[xm+j-i] * a2[xm-j+2]);

      icarry := icarry + inum;
      if icMax < icarry then icMax := icarry;
      if inMax < inum   then inMax := inum;
      inum   := icarry mod 1000000;
      icarry := icarry div 1000000;
      countr := countr + 1;
      a3[countr] := inum;
   end;
end;
if icarry >= 1 then begin
   countr     := countr + 1;
   a3[countr] := icarry;
end;

so := IntToStr(a3[countr]);
for i := countr-1 downto 1 do begin
    snxt6 := IntToStr(a3[i]+1000000);
    so := so+ snxt6[2]+ snxt6[3]+ snxt6[4]+ snxt6[5]+ snxt6[6]+ snxt6[7];
end;

while so[1] = '0' do                       // leading zeroes may exist
    so := copy(so,2,length(so));

result := so;
end;

// ============================================= =================================

测试电话:

StrText:= Str6Product('742136061320987817587158718975871','623450632948509826743508972875');

答案 2 :(得分:0)

我应该补充一点,您应该能够使用相同的方法添加大数字 - 从右到左,将字符串分段为16个字节的块,然后将这些块转换为uInt64变量。首先添加最低有效位,如果它产生第17个字节,则将其转移到第二个最低有效块,将这两个PLUS添加到任何进位等。否则,将每个16字节块转换回字符串并相应地连接。

从整数到字符串的转换,反之亦然是一种痛苦,但对于大数字运算来说是必需的。