mca*_*a64 1 delphi floating-point
我使用Delphi 7现在FloatToStr(64)返回
64,0000017441
当在使用Direct3D代码的同一进程中加载不同的模块时.
返回值是
64
正如预期的那样,当其他模块在此过程中不活动时.
为什么FloatToStr()的输出会根据执行的其他不相关代码而改变,以及如何始终获得浮点值的可靠且一致的字符串表示?
FloatToStr()的行为差异可以在以下示例代码中看到:
{$APPTYPE CONSOLE}
program Project1;
uses
SysUtils;
begin
Writeln('FloatToStr(64) = ', FloatToStr(64));
Set8087CW(Get8087CW and $FCFF);
Writeln('FloatToStr(64) = ', FloatToStr(64));
end.
Run Code Online (Sandbox Code Playgroud)
在外部插件代码中,在“ display.cpp”代码中
hr = d3d->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
D3DCREATE_NOWINDOWCHANGES | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE,
&d3dpp, &d3ddev );
Run Code Online (Sandbox Code Playgroud)
添加标志“ D3DCREATE_FPU_PRESERVE”,使代码为:
hr = d3d->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hwnd,
D3DCREATE_NOWINDOWCHANGES | D3DCREATE_HARDWARE_VERTEXPROCESSING | D3DCREATE_PUREDEVICE | D3DCREATE_FPU_PRESERVE,
&d3dpp, &d3ddev );
Run Code Online (Sandbox Code Playgroud)
如果省略此代码,则Direct 3D会更改FPU对当前线程使用的精度,并且您会看到不太精确的值。
另请参阅http://blogs.msdn.com/b/tmiller/archive/2004/06/01/145596.aspx
替代方法(当您不能或不想更改其他插件代码时)是在显示浮点值时使用显式格式。
使用
s:= FormatFloat('0.##', x);
Run Code Online (Sandbox Code Playgroud)
代替
s:= FloatToStr(X);
Run Code Online (Sandbox Code Playgroud)
这将始终将值四舍五入到小数点后两位,并且在小数点分隔符后不显示尾随零。当两位最高的数字为0时,它将不显示任何十进制分隔符。
另一种选择是让代码在单独的线程中运行,因为FPU精度设置是针对每个线程的。
另一种选择是执行
Reset8087CW;
Run Code Online (Sandbox Code Playgroud)
在代码中调用FloatToStr()之前。但是,这可能会使Direct3D混乱并在那里产生错误。
小智 5
提供一个简单的控制台应用程序,复制您正在看到的行为,以及一些更详细的解释:
{$APPTYPE CONSOLE}
program Project1;
uses
SysUtils;
begin
Set8087CW(Get8087CW and $FCFF);
Writeln('FloatToStr(64) = ', FloatToStr(64));
end.
Run Code Online (Sandbox Code Playgroud)
输出:
FloatToStr(64) = 64.000001744411
单步执行调试器,转换64为十进制表示的代码最终会调用
function _Pow10(val: Extended; Power: Integer): Extended;
Run Code Online (Sandbox Code Playgroud)
用val = 64,Power = 16计算64 * 10**16.然后将其转换为整数640000000000000000,从中提取十进制数字,并在其中放置小数点.这在默认的FPU模式下会很好,它会640000000000000000精确地产生,但在这里使用的FPU模式中,可用的精度较低,而不足以表示该数字的精度.它会向上舍入到最接近的可表示数字,并且后续代码正确地提取小数字会 看到最后的数字不是0.
这个问题是2004年未解决的QC报告的主题:QC#7275.