我们最近开始创建64位构建的应用程序。在比较测试期间,我们发现64位构建的计算方式不同。我有一个代码示例,演示了两个版本之间的区别。
var
currPercent, currGross, currCalcValue : Currency;
begin
currGross := 1182.42;
currPercent := 1.45;
currCalcValue := (currGross * (currPercent * StrToCurr('.01')));
ShowMessage(CurrToStr(currCalcValue));
end;
如果在32位版本中逐步执行此操作,则使用17.1451计算currCalcValue,而使用17.145返回64位版本。
为什么64位构建不计算额外的小数位?所有变量都定义为4个十进制货币值。
答案 0 :(得分:14)
这是我的SSCCE基于您的代码。请注意控制台应用程序的使用。让生活变得更加简单。
{$APPTYPE CONSOLE}
uses
SysUtils;
var
currPercent, currGross, currCalcValue : Currency;
begin
currGross := 1182.42;
currPercent := 1.45;
currCalcValue := (currGross * (currPercent * StrToCurr('.01')));
Writeln(CurrToStr(currCalcValue));
Readln;
end.
现在看一下生成的代码。前32位:
Project3.dpr.13: currCalcValue := (currGross * (currPercent * StrToCurr('.01'))); 0041C409 8D45EC lea eax,[ebp-$14] 0041C40C BADCC44100 mov edx,$0041c4dc 0041C411 E8A6A2FEFF call @UStrLAsg 0041C416 8B1504E74100 mov edx,[$0041e704] 0041C41C 8B45EC mov eax,[ebp-$14] 0041C41F E870AFFFFF call StrToCurr 0041C424 DF7DE0 fistp qword ptr [ebp-$20] 0041C427 9B wait 0041C428 DF2DD83E4200 fild qword ptr [$00423ed8] 0041C42E DF6DE0 fild qword ptr [ebp-$20] 0041C431 DEC9 fmulp st(1) 0041C433 DF2DE03E4200 fild qword ptr [$00423ee0] 0041C439 DEC9 fmulp st(1) 0041C43B D835E4C44100 fdiv dword ptr [$0041c4e4] 0041C441 DF3DE83E4200 fistp qword ptr [$00423ee8] 0041C447 9B wait
64位:
Project3.dpr.13: currCalcValue := (currGross * (currPercent * StrToCurr('.01'))); 0000000000428A0E 488D4D38 lea rcx,[rbp+$38] 0000000000428A12 488D1513010000 lea rdx,[rel $00000113] 0000000000428A19 E84213FEFF call @UStrLAsg 0000000000428A1E 488B4D38 mov rcx,[rbp+$38] 0000000000428A22 488B155F480000 mov rdx,[rel $0000485f] 0000000000428A29 E83280FFFF call StrToCurr 0000000000428A2E 4889C1 mov rcx,rax 0000000000428A31 488B0510E80000 mov rax,[rel $0000e810] 0000000000428A38 48F7E9 imul rcx 0000000000428A3B C7C110270000 mov ecx,$00002710 0000000000428A41 48F7F9 idiv rcx 0000000000428A44 488BC8 mov rcx,rax 0000000000428A47 488B0502E80000 mov rax,[rel $0000e802] 0000000000428A4E 48F7E9 imul rcx 0000000000428A51 C7C110270000 mov ecx,$00002710 0000000000428A57 48F7F9 idiv rcx 0000000000428A5A 488905F7E70000 mov [rel $0000e7f7],rax
请注意,32位代码对FPU执行算术运算,但64位代码使用整数运算执行算法。这是关键的区别。
在32位代码中,执行以下计算:
现在,在64位代码中,它有点不同。因为我们一直使用64位整数。它看起来像这样:
所以问题是64位编译器在每个中间步骤中除以10,000。大概是为了避免溢出,更可能是64位整数而不是浮点寄存器。
是这样做的计算:
100 * 14,500 * 11,824,200 / 10,000 / 10,000
它会得到正确的答案。
答案 1 :(得分:0)
从XE5u2开始,到目前正在编写XE6u1时已经修复了这个问题。