gpt4 book ai didi

Delphi Roundto 和 FormatFloat 不一致

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

我在 Delphi 2010 中遇到了舍入奇怪的问题,其中一些数字在 roundto 中向下舍入,但在 formatfloat 中向上舍入。

我完全意识到十进制数的二进制表示有时会给出误导性的结果,但在这种情况下,我希望 formatfloat 和 roundto 给出相同的结果。

我还看到过一些建议,认为应该使用“Currency”来实现这种目的,但正如您在下面看到的,Currency 和 Double 给出了相同的结果。

program testrounding;

{$APPTYPE CONSOLE}

{$R *.res}

uses
System.SysUtils,Math;

var d:Double;
c:Currency;
begin
d:=534.50;
c:=534.50;
writeln('Format: ' +formatfloat('0',d));
writeln('Roundto: '+formatfloat('0',roundto(d,0)));
writeln('C Format: ' +formatfloat('0',c));
writeln('C Roundto: '+formatfloat('0',roundto(c,0)));
readln;
end.

结果如下:

Format: 535
Roundto: 534
C Format: 535
C Roundto: 534

我看过Why is the result of RoundTo(87.285, -2) => 87.28并且建议的补救措施似乎并不适用。

最佳答案

首先,我们可以从问题中删除 Currency,因为您使用的两个函数没有 Currency 重载。该值将转换为 IEEE754 浮点值,然后遵循与 Double 代码相同的路径。

让我们首先看一下RoundTo。使用调试器或附加的 Writeln 可以快速检查 RoundTo(d,0) = 534。这是为什么?

嗯,documentation对于 RoundTo 说:

Rounds a floating-point value to a specified digit or power of ten using "Banker's rounding".

事实上,在RoundTo的实现中,我们看到舍入模式在恢复到其原始值之前暂时切换为TRoundingMode.rmNearest。舍入模式仅适用于值正好是两个整数之间的一半时。我们这里的情况正是如此。

因此银行家四舍五入适用。这意味着当该值正好是两个整数之间的一半时,舍入算法会选择相邻的偶数整数。

因此,RoundTo(534.5,0) = 534 是有意义的,同样您可以检查 RoundTo(535.5,0) = 536

理解FormatFloat是完全不同的事情。坦率地说,它的行为有些不透明。它在不同平台的代码中执行不同的临时舍入。例如,它在 32 位 Windows 上是汇编程序,但在 64 位 Windows 上是 Pascal。总体方法似乎是获取浮点值的尾数,将其转换为整数,将其转换为文本数字,然后根据这些文本数字执行舍入。执行舍入时不会考虑当前的舍入模式,并且该算法似乎实现了 round half away from zero policy 。然而,即使如此,也不能针对所有可能的浮点值稳健地实现。它对于您的值可以正确工作,但对于尾数中包含更多数字的值,算法会崩溃。

事实上,众所周知,用于在浮点值和文本之间进行转换的 Delphi RTL 例程从根本上被设计破坏了。 Delphi RTL 中没有任何例程可以正确地从文本转换为浮点型,或从浮点型转换为文本。事实上,我最近实现了自己的转换例程,它基于其他语言运行时使用的现有开源代码正确地执行了此操作。总有一天我会抽出时间发布此代码以供其他人使用。

我不确定您的确切需求是什么,但如果您希望对舍入进行一些控制,那么如果您负责舍入,则可以这样做。虽然 RoundTo 始终使用 Banker 舍入模式,但您也可以使用 Round 它使用当前舍入模式。这将允许您使用您选择的舍入算法(通过调用SetRoundMode)执行舍入,然后您可以将舍入值转换为文本。这就是关键。将值保留为算术类型,执行舍入,并且仅在应用正确舍入后的最后一刻才转换为文本。

关于Delphi Roundto 和 FormatFloat 不一致,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57193437/

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