gpt4 book ai didi

delphi - StrToFloat 无法报告 Delphi 64 位中的无效 float

转载 作者:行者123 更新时间:2023-12-03 14:34:12 25 4
gpt4 key购买 nike

以下代码尝试转换远远超出 double 范围的值

StrToFloat('1e99999999')

在使用 Windows 32 位编译器的 Delphi 10.2r3 中正确报告错误的浮点值,但是当使用 Windows 64 位编译器编译时,它会默默地返回 0(零)。

有没有办法让StrToFloat在浮点值不正确时报告错误?

我尝试过 TArithmeticException.exOverflow,但在这种情况下没有效果。

我也尝试过 TArithmeticException.exPrecision,但它在许多常见的近似情况下触发(例如,它在转换“1e9”时触发)。

Delphi 10.2 更新 3 中注意到了问题

附录:为了解决该问题,我已经开始了字符串到 double 转换的洁净室替代实现,带有测试的初始版本可以在 dwscript commit 2ba1d4a 中找到。

最佳答案

这是使用 StrToFloat PUREPASCAL 版本的所有 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
  • 在读取 StrToFloat 之前预处理字符串并处理超出范围的指数。
  • 使用 C 运行时库中执行相同任务的函数之一。

最后,我很感谢您提出这个问题,因为我可以看到我自己的程序受到了这个缺陷的影响,所以我现在可以修复它!

更新:

您可能还有兴趣查看我在调查时发现的相关错误:RSP-20334 。您可能会惊讶地发现,在使用 StrToFloat 的 PUREPASCAL 版本时,StrToFloat('马') 返回 1936.0。诀窍在于,传递给 StrToFloat 的字符是非拉丁数字,在本例中 U+07C0 .

关于delphi - StrToFloat 无法报告 Delphi 64 位中的无效 float ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49736322/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com