delphi – 简单的浮点数丢失精度
我正在使用Delphi XE2 Update 3.即使是最简单的浮点数(如3.7)也存在精度问题.鉴于此代码(32位控制台应用程序):
program Project1; {$APPTYPE CONSOLE} {$R *.res} uses System.SysUtils; var s: Single; d: Double; x: Extended; begin Write('Size of Single ----- '); Writeln(SizeOf(Single)); Write('Size of Double ----- '); Writeln(SizeOf(Double)); Write('Size of Extended --- '); Writeln(SizeOf(Extended)); Writeln; s := 3.7; d := 3.7; x := 3.7; Write('"s" is '); Writeln(s); Write('"d" is '); Writeln(d); Write('"x" is '); Writeln(x); Writeln; Writeln('Single Comparison'); Write('"s > 3.7" is '); Writeln(s > 3.7); Write('"s = 3.7" is '); Writeln(s = 3.7); Write('"s < 3.7" is '); Writeln(s < 3.7); Writeln; Writeln('Double Comparison'); Write('"d > 3.7" is '); Writeln(d > 3.7); Write('"d = 3.7" is '); Writeln(d = 3.7); Write('"d < 3.7" is '); Writeln(d < 3.7); Writeln; Writeln('Extended Comparison'); Write('"x > 3.7" is '); Writeln(x > 3.7); Write('"x = 3.7" is '); Writeln(x = 3.7); Write('"x < 3.7" is '); Writeln(x < 3.7); Readln; end. 我得到这个输出: Size of Single ----- 4 Size of Double ----- 8 Size of Extended --- 10 "s" is 3.70000004768372E+0000 "d" is 3.70000000000000E+0000 "x" is 3.70000000000000E+0000 Single Comparison "s > 3.7" is TRUE "s = 3.7" is FALSE "s < 3.7" is FALSE Double Comparison "d > 3.7" is TRUE "d = 3.7" is FALSE "d < 3.7" is FALSE Extended Comparison "x > 3.7" is FALSE "x = 3.7" is TRUE "x < 3.7" is FALSE 您可以看到extended是唯一正确评估的类型.我认为使用像3.14159265358979323846这样复杂的浮点数时,精度只是一个问题,而不是像3.7那样简单.使用单一类型时的问题是有道理的.但为什么不加倍工作呢? 解决方法
必读:
What Every Computer Scientist Should Know About Floating-Point Arithmetic,David Goldberg.
这个问题不是精确问题.相反,问题是可表示性问题.首先,让我们重新说明浮点数用于表示实数.有无穷无尽的实数.当然,整数也是如此.但是这里的区别在于,在特定范围内,存在有限数量的整数但是具有无限数量的实数.实际上,与originally shown by Cantor一样,任何有限的实数区间都包含无数个实数值. 很明显,我们无法在有限的机器上表示所有实数.那么,我们可以代表哪些数字?那么,这取决于数据类型. Delphi浮点数据类型使用二进制表示.单(32位)和双(64位)类型符合IEEE-754标准.扩展(80位)类型是Intel特定类型.在二进制浮点中,可表示的数字具有形式k2n,其中k和n是整数.请注意,我并未声称此表单的所有数字均可表示.这是不可能的,因为有无限数量的这种数字.相反,我的观点是所有可表示的数字都是这种形式. 可表示的二进制浮点数的一些示例包括:1,0.5,0.25,0.75,1.25,0.125,0.375.您的值3.7不能表示为二进制浮点值. 与代码相关的含义是,它没有按照您的预期执行.您希望与3.7的值进行比较.但相反,您将与最接近的完全可表示的值进行比较,以达到3.7.作为实现细节的问题,这个最接近的可表示的值是在扩展精度的上下文中.这就是为什么使用扩展的版本看起来像你期望的那样.但是,不要认为这意味着您的变量x等于3.7.实际上,它等于最接近的可表示的扩展精度值为3.7. Rob Kennedy的most useful website可以显示与特定数字最接近的可表示值.在3.7的情况下,这些是: 3.7 = + 3.70000 00000 00000 00004 33680 86899 42017 73602 98112 03479 76684 57031 25 3.7 = + 3.70000 00000 00000 17763 56839 40025 04646 77810 66894 53125 3.7 = + 3.70000 00476 83715 82031 25 这些按扩展,双,单的顺序显示.换句话说,这些是变量x,d和s的值. 如果您查看这些值,并将它们与最接近扩展到3.7的值进行比较,您将看到为什么程序会生成它所做的输出.这里的单精度值和双精度值都大于扩展值.这是你的程序告诉你的. 我不想就如何比较浮点值提出任何建议.这样做的最佳方式总是非常关键地取决于具体问题.没有全面的建议可以提供. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |