Eri*_*nge 22 delphi 64-bit delphi-10.2-tokyo
以下代码尝试将值转换为远超出双精度范围
StrToFloat('1e99999999')
Run Code Online (Sandbox Code Playgroud)
使用Windows 32位编译器在Delphi 10.2r3中正确报告错误的浮点值,但是当使用Window 64位编译器编译时,它会静默返回0(零).
当浮点值不正确时,有没有办法让StrToFloat报告错误?
我已经尝试过TArithmeticException.exOverflow,但在这种情况下这没有效果.
我也尝试过TArithmeticException.exPrecision,但它在许多通常的近似情况下触发(在转换'1e9'时触发它).
Delphi 10.2 update 3注意到了这个问题
附录:要解决这个问题,我已经启动了一个洁净室替代实现字符串到双重转换,初始版本带有测试可以在dwscript commit 2ba1d4a中找到
Dav*_*nan 23
这是使用PUREPASCAL版本的所有Delphi版本中存在的缺陷StrToFloat
.映射到InternalTextToExtended
哪个读取指数如下:
function ReadExponent: SmallInt;
var
LSign: SmallInt;
begin
LSign := ReadSign();
Result := 0;
while LCurrChar.IsDigit do
begin
Result := Result * 10;
Result := Result + Ord(LCurrChar) - Ord('0');
NextChar();
end;
if Result > CMaxExponent then
Result := CMaxExponent;
Result := Result * LSign;
end;
Run Code Online (Sandbox Code Playgroud)
问题是的位置
if Result > CMaxExponent then
Run Code Online (Sandbox Code Playgroud)
这个测试是在循环内部,在这个代码的asm x86版本中.如上所述,使用循环外的最大指数测试,16位有符号整数结果值对于指数而言太小99999999
.读取指数时,Result
溢出的值变为负值.因此,对于您的示例,事实证明使用了指数-7937
而不是99999999
.当然,这导致零值.
这是一个明显的错误,我已经提交了一个错误报告:RSP-20333.
至于如何解决问题,我不知道Delphi RTL中执行此任务的另一个功能.所以我认为你需要做以下其中一件事:
StrToFloat
.StrToFloat
.最后,我很感谢您提出这个问题,因为我可以看到我自己的程序受到这个缺陷的影响,所以我现在可以解决它!
更新:
您可能还有兴趣查看我在调查时发现的相关错误:RSP-20334.您可能会意识到StrToFloat('?')
,当使用PUREPASCAL版本时StrToFloat
,会返回1936.0
.诀窍是传递给的字符StrToFloat
是非拉丁数字,在这种情况下是U + 07C0.