在Delphi中,我如何确定何时使用Real、Real48、Double或Single数据类型?

15
我大部分的应用程序都涉及金融计算,包括付款和利率计算。我希望了解如何确定最适合使用的 Delphi 数据类型。
如果我使用数据库存储这些值,并且我已将该数据库中的字段定义为具有两位小数的十进制值,请问哪种 Delphi 数据类型最符合这种情况?
我是否应该在 Delphi 中使用舍入公式将结果格式化为两位小数,然后再将值存储到数据库中?如果是这样,做到最好的方法是什么?

梅森的建议是正确的。不管怎样,Real48永远不合适。 - David Heffernan
3
@David:同意。 Real48是一种古老的类型,仅保留用于向后兼容,并且不应在现代代码中使用。 - Mason Wheeler
你还忘记了浮点类型的“Extended”和定点类型的“Currency”。 - CodesInChaos
使用浮点数时,舍入是必须的。始终如此。Real48 用于软件浮点数(比硬件精度略高,但速度慢)。关于有效数字:Single 看起来只能勉强满足要求,因此可以使用 Double(本质上与 Real 相同)。请查看此表格:http://docwiki.embarcadero.com/RADStudio/en/Simple_Types#Fundamental_Win32_real_types - Premature Optimization
@Downvoter等:Real48不再是软件浮点数了。它只是被转换为Extended,传递给FPU,然后将结果转换回来。 - Rudy Velthuis
2个回答

11

在进行此类计算时,不要使用浮点类型如Real、Single或Double。它们对于像0.01或1234.995这样的小数值并不好用,因为它们必须进行近似计算。

您可以使用Currency,这是一种固定点类型,但仍然限制为4个小数位。

尝试使用我的Decimal类型,它具有28-29位数字和一个十进制指数,因此非常适合进行此类计算。唯一的缺点是它没有FPU支持(但是还是用汇编语言编写的),所以它不像内置类型那样快速。它与.NET中使用的Decimal类型相同(但稍微更快),并且与Mac上使用的Decimal类型非常相似。


你打算升级到新的XE2目标吗? - David Heffernan
是的,我计划用x64汇编重做汇编器。我想这应该会使一些事情变得更容易(更大的寄存器,更多的寄存器,因此可能根本不需要使用局部变量),但有些事情则不然(x64汇编器在序言和尾声代码方面要严格一些等)。 - Rudy Velthuis
@Rudy - 谢谢提供链接。不幸的是,我无法使用您的Decimal类型,原因如下。我想将所有计算推到数据库中的存储过程中。我发现 Delphi、MS Sql Server 和 ElevateDB 的数学计算略有不同。如果我在 Delphi 中进行计算并将结果写入数据库,则需要进行多个 DB I/O 操作。如果我在存储过程中进行计算,则需要确保计算与 Delphi 相同。但是,我接受了您的答案,因为它让我回头重新思考了整个问题。 - Michael Riley - AKA Gunny

10
如果您想进行财务计算,请勿使用任何浮点型/实数类型。Delphi有一个称为Currency的类型,它是一个带有4位小数的定点值,这应该正是您所需要的。

1
@David Heffernan:货币不仅以十进制为基础,还以二进制为基础。货币以一个缩放的64位整数存储,其中四个最低有效数字隐含地表示小数位。 - GJ.
3
@Cape:乘法和除法是可交换的。建议尝试使用0.05 * 1000 / 365。 - Mason Wheeler
顺便提一下,与其他80x87类型一样,“货币”也会累积计算误差。 - Premature Optimization
@David 看看生成的汇编代码,你会发现 currency 算术是用 x87 操作码实现的(至少在32位Delphi中是这样)。但由于它使用了这些操作码的 "i"(整数)版本,所以这里没有浮点舍入或错误。但你可以安全地使用 PInt64(@aCurcr) 类型转换(*10000)进行货币计算。 - Arnaud Bouchez
@Arnaud 好的,我想我知道它为什么这样做了。这是为了避免溢出,并利用大多数在货币有效范围内的整数可以在IEEE754数据类型中精确表示的事实。尽管对我来说还有点奇怪。 - David Heffernan
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接