Delphi 如何对任意大小的整数执行算术?
我的原始代码在这里Delphi 如何对任意大小的整数执行算术?,delphi,delphi-7,Delphi,Delphi 7,我的原始代码在这里 function AddNumStrings(Str1, Str2: string): string; var i: integer; carryStr: string; worker: integer; workerStr: string; begin Result:= inttostr(length(Str1)); Result:= ''; carryStr:= '0'; // make numbers the same length
function AddNumStrings(Str1, Str2: string): string;
var
i: integer;
carryStr: string;
worker: integer;
workerStr: string;
begin
Result:= inttostr(length(Str1));
Result:= '';
carryStr:= '0';
// make numbers the same length
while length(Str1) < length(Str2) do Str1:= '0' + Str1;
while length(Str1) > length(Str2) do Str2:= '0' + Str2;
i:= 0;
while i < length(Str1) do begin
worker:= strtoint(copy(Str1, length(Str1) - i, 1)) + strtoint(copy(Str2, length(Str2) - i, 1)) + strtoint(carryStr);
if worker > 9 then begin
workerStr:= inttostr(worker);
carryStr:= copy(workerStr, 1, 1);
Result:= copy(workerStr, 2, 1) + Result;
end else begin
Result:= inttostr(worker) + Result;
carryStr:= '0';
end;
inc(i);
end; { while }
if carryStr <> '0' then Result:= carryStr + Result;
Application.ProcessMessages;
end;
function yeni(s1, s2: string): string;
var
j, i, k: integer;
c: char;
s: string;
begin
k:= length(s2);
j:= length(s1) - length(s2);
for i:= j downto 1 do begin
c:= s1[i];
k:= k + 1;
if (c <> '9') and (c <> '0') then begin
s:= copy(s1, i, k);
s:= AddNumStrings(s, s2);
Setlength(s1, i - 1);
Result:= s1 + s;
break;
end;
Application.ProcessMessages;
end;
procedure TForm1.Button13Click(Sender: TObject);
var
i, k: integer;
s: Ansistring;
begin
s:= '1111';
for i:= 1 to 1000000 do begin
for k:= 1 to 120 do begin
s:= yeni(s, '4');
end;
end;
end;
end.
函数addNumString(Str1,Str2:string):string;
变量
i:整数;
卡里斯特:弦;
工作者:整数;
workerStr:字符串;
开始
结果:=inttostr(长度(Str1));
结果:='';
carryStr:=“0”;
//使数字长度相同
而长度(Str1)length(Str2)做Str2:=“0”+Str2;
i:=0;
当我9,则开始
workerStr:=inttostr(工人);
carryStr:=副本(workerStr,1,1);
结果:=复制(workerStr,2,1)+结果;
结束,否则开始
结果:=inttostr(工人)+结果;
carryStr:=“0”;
终止
公司(一);
终止{while}
如果carryStr“0”,则结果:=carryStr+Result;
Application.ProcessMessages;
终止
函数yeni(s1,s2:string):string;
变量
j、 i,k:整数;
c:半焦;
s:字符串;
开始
k:=长度(s2);
j:=长度(s1)-长度(s2);
对于i:=j向下至1,开始
c:=s1[i];
k:=k+1;
如果是(c'9')和(c'0'),则开始
s:=副本(s1,i,k);
s:=AddNumStrings(s,s2);
设定长度(s1,i-1);
结果:=s1+s;
打破
终止
Application.ProcessMessages;
终止
程序TForm1.按钮13点击(发送方:TObject);
变量
i、 k:整数;
s:翻译;
开始
s:='1111';
对于i:=1到1000000,开始
对于k:=1到120,开始
s:=yeni(s,'4');
终止
终止
终止
终止
最后,我的字符串s
长度必须为100000000。但我想这需要68天。
如何加速此代码 您的代码被的变体阻塞了。每次这样添加两个字符串时,Delphi RTL都必须增加字符串的大小,这可能涉及分配一个新的、更大的字符串并复制旧字符串,然后释放旧字符串。当你这样做1000万次时,所有的内存复制和重新分配都会累加起来
要使其快速运行,您需要做的是预先计算完成的字符串的长度,然后在
s
上调用SetLength
,并从一开始就分配大字符串。之后,跟踪尚未“填充”的最高字符的索引。每个IntToStr
调用都将生成一个新字符串;插入|
字符,然后将IntToStr
结果复制过来,同时更新索引。这将大大减少代码运行所需的时间。显然,这是一个愚蠢的示例,但您可以做以下几件事:
string:=string+someotherstring
Delphi将执行
concat
操作。这涉及调整字符串分配的大小(如果需要)并将字符串(如果需要)移动到内存中的新位置。如果您多次这样做,所有的存储分配都将开始累积。事实上,如果您将函数的运行次数翻倍到20000000次,您会发现运行时的运行次数会翻倍以上。
因此,您可以避免这种胡说八道,并将那些代价高昂的函数移出循环 了解您的数据
只要
s[index]=0
,任何乘法都将为0。你可以利用这些知识大大加快速度。有人称之为欺骗;在这种情况下,这可能是正确的,但在更复杂的情况下,了解数据将做什么可以让您获得非常好的加速。此外,您知道将一位数字乘以九永远不会产生大于81的结果,因此您不需要检查超过2个字符 将内容移出循环
一旦你知道了你的数据,你就可以把数据从循环中移出,所以你不需要做很多次,只需要做一次。
即使循环外的东西比循环内的东西花费的时间长10000倍。这仍然是一笔不错的交易 除非可以预测,否则不要跳转
在这种情况下,这不适用,因为函数在输出稳定的零流时会很快稳定下来,但我还是将其放入演示中。
事实上,这里的
if
比noif
更快,因为跳转打破了依赖链
代码示例
procedure TForm1.Button4Click(Sender: TObject);
const
NumberOfCharsForKToSettleTo0 = 10;
ManyTimes = 10 * 1000 * 1000
var
i,j,k,l:integer;
s:string;
begin
//preallocate the length of the string
SetLength(s, 4 + (ManyTimes * length('|1')) + NumberOfCharsForKToSettleTo0);
s:='1369';
l:= 4;
for i:=1 to ManyTimes do begin
j:=i mod 9;
//k:=strtoint(s[Length(s)])*j; don't use strtoint
k:= ord(s[l]) - ord('0');
k:= k*j;
//s:=s+'|'+inttostr(k);
inc(l);
s[l]:= '|';
inc(l);
s[l]:= chr(k div 10+ord('0'));
inc(l,integer(k>9)); //avoid jumps/ifs that are hard to predict.
s[l]:= chr(k+ord('0'));
end;
end;
您正在尝试使用字符串执行任意精度的算术运算。
这是个坏主意 改用bigint库。 它使用整数数组来执行此任务。
一个不错的可在以下网站下载:
或者根据LURD的建议:预先分配整个字符串,然后填写内容。如果您学会了如何缩进代码,可能会有所帮助。如果你没有问如何快速完成愚蠢的、毫无意义的任务,而是告诉我们真正的问题,这也会有所帮助。可能重复的“请勿在其他帐户下再次发布相同的问题”。相反,编辑并改进你的内容,这样我们就可以知道你在问什么。@DavidHeffernan:要知道他想做什么并不难,说真的,这一切真的有必要吗?如果你把一半的精力投入到侮辱和贬低这张海报上,而实际上是想帮助他,那么你现在已经找到了答案…@mason回答这个问题很容易。可以在编译时计算字符串!这不是一个正确的问题。提问者说真正的问题是不同的。肯已经给出了和你一样的答案,基本上是在他问同样的问题时。除非我们告诉他问正确的问题,否则他会一直问同一个问题