Delphi减法错误?怎么解决这个问题?

时间:2013-11-29 19:21:53

标签: delphi

我的代码如下:

debt:=debt+(p_sum-p_addition-p_paid);

在此行之前

debt:=0;
p_sum:=36;
p_addition:=3.6;
p_paid:=32.4;

此行债务变量获得的值如下:1.3322676e-15;

enter image description here

2 个答案:

答案 0 :(得分:4)

您正在使用二进制浮点运算。您的非整数值在二进制浮点中无法表示。因此,你会受到舍入误差的影响。

您实际上想要使用十进制而不是二进制表示。如果你这样做,那么你的所有值都将被准确表示,算术将是精确的。

在Delphi中,十进制实值数据类型是Currency。我建议您切换到货币进行这些计算。

有关此主题的必读内容为What Every Computer Scientist Should Know About Floating-Point Arithmetic

答案 1 :(得分:1)

您所看到的只是浮点值的科学记数法。这只是在监视列表中显示值的几种不同方式之一。在这种情况下,“正常格式”将是:0.0000000000000013322676(注意有15个零。)监视列表具有18位数的限制来显示该值。因此,为了尽可能准确地为您提供 程序员 值,它会使用科学记数法。

每当浮点数非常小(如本例所示)或非常大时,以科学计数法显示浮点数就更有效率。计算产生这个非常小的结果而不是0的原因是由于舍入误差,如David's Answer中所述。

至于将值“恢复为正常格式”,没有意义。该值只是表示计算结果的内存中的值。基本上是一系列字节(在这个特殊情况下$ 3B $ AA $ 11 $ F7 $ FF $ FF $ D $ $ 3C)。你不想摆弄这个值,否则你可能会引入更多的舍入错误。此外,作为程序员,您应该能够阅读更准确的科学记数法。

但是,在某些时候,您可能希望将此值显示给 用户 。在这种情况下,您将创建值的适当字符串表示形式。最合适的格式取决于您的应用程序的性质。 (即在某些情况下,科学记数法仍然是最好的。)

如果您想使用固定浮点表示法,可以使用FormatFloat('0.00', Value);在您的情况下,非常小的数字将四舍五入为0.00。 (顺便说一句,你甚至可以将它放入你的观察名单。)
有关详细信息,请阅读FormatFloat上的帮助。您可以选择包含/排除千位分隔符,甚至可以使用您自己的显示格式的科学记数法。

阅读科学记谱法

一旦理解了格式,科学记数法实际上很容易阅读:
Number e Exponent例如1.3322676 E -15

这基本上意味着:取Number并将其乘以10 Exponent的幂。 (这相当于将小数点左/右Exponent位数移位。)负指数使数字变小,正指数使数字变大。

一些例子:

  • 1纳秒是1.0e-9秒,或0.000000001秒
  • 1秒是1.0e + 9纳秒,或100000000纳秒
  • 1.5e0 = 1.5
  • 1.5e1 = 15
  • 1.5e-1 = 0.15

科学记数法的一个重要惯例是指数前面的数字总是在小数点的左边正好使用1位数(非零)(指数已相应调整)。这样就可以通过查看指数来轻松比较两个数字的相对大小。 E.g。

  • 1.01846e + 7大于9.999999999e + 6
  • 1.01846e-6大于9.999999999e-7
  • 1.234e + 250远大于9.876e-250
  • 1.234e + 3大于1.1234e + 3(只有当指数相等时才需要比较实际数字)。