StrToFloat无法在Delphi 64位中报告无效的浮点数
以下代码尝试将值转换为超出双精度范围
StrToFloat('1e99999999') 使用Windows 32位编译器在Delphi 10.2r3中正确报告错误的浮点值,但是当使用Window 64位编译器进行编译时,它会以静默方式返回0(零)。 当浮点值不正确时,有没有办法让StrToFloat报告错误? 我已经尝试过TArithmeticException.exOverflow,但在这种情况下这没有效果。 我也尝试过TArithmeticException.exPrecision,但它在许多通常的近似情况下触发(f.i.它在转换’1e9’时触发)。 Delphi 10.2 update 3注意到了这个问题 附录:为解决这个问题,我已经启动了一个洁净室替代实现字符串到双重转换,初始版本的测试可以在dwscript commit 2ba1d4a找到 解决方法
这是使用PUREPASCAL版本的StrToFloat的所有Delphi版本中存在的缺陷。这映射到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; 问题是的位置 if Result > CMaxExponent then 这个测试意味着在循环内部,并且在这个代码的asm x86版本中。如上所述,使用循环外的最大指数测试,16位有符号整数结果值对于指数99999999来说太小。当读取指数时,Result中的值溢出,并变为负数。因此,对于您的示例,事实证明使用的指数为-7937而不是99999999.当然,这会导致值为零。 这是一个明显的错误,我已经提交了一个错误报告:RSP-20333。 至于如何解决问题,我不知道Delphi RTL中执行此任务的另一个功能。所以我认为您需要执行以下操作之一: >滚动你自己的StrToFloat。 最后,我很感谢您提出这个问题,因为我可以看到我自己的程序受到此缺陷的影响,因此我现在可以解决它! 更新: 您可能还有兴趣查看我在调查时发现的相关错误:RSP-20334。您可能会惊讶地发现,StrToFloat(‘?’)在使用PUREPASCAL版本的StrToFloat时返回1936.0。诀窍是传递给StrToFloat的字符是非拉丁数字,在本例中为U+07C0。 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |