任何人都可以解释这种怪异:
Dim result as single = 0
result = CType("8.01", Single) * 100 ' result=801.0 as expected
result = CType("8.02", Single) * 100 ' result=802.000061 --- not expected
更进一步
result = 8.02 * 100 ' result = 802.0 as expected
任何人都可以解释这种怪异:
Dim result as single = 0
result = CType("8.01", Single) * 100 ' result=801.0 as expected
result = CType("8.02", Single) * 100 ' result=802.000061 --- not expected
更进一步
result = 8.02 * 100 ' result = 802.0 as expected
Single
(或float
)只有七个有效数字,因此任何可能打印的超出这些数字的内容几乎都是伪造的。这是浮点运算的正常产物。您的号码最多只能依赖小数点后 4 位数字(因为小数点前已经有三位有效数字)。
进一步阐述,数字 8.01 和 8.02 不能使用二进制存储精确表示(因为 0.01 和 0.02 都不能用 1/2 n形式的分数之和精确表示)。细节可能因数字而异,但在使用此类数字时,您可能会看到超出正常精度范围的无关数字。
这不会影响 801 和 802可以精确表示的事实,但在这种情况下您没有确切的数字开始。
ETA:实际上,当您直接包含计算时,您看到的只是这样:编译器将为您评估计算并简单地写入802
程序。您可以使用 Reflector 来验证这一点。源代码中的浮点文字也可能Double
默认情况下,因此您可以从这里开始具有更高的精度。如果result
是 aSingle
这将被向下转换,Single
并且小数点后第 16 位的错误被简单地丢弃,因为它Single
无论如何都无法适应。
这是由于浮点数在内存中表示方式的限制。阅读维基百科页面以了解完整的内幕——这不是错误,也不是 .net 特有的东西。
编辑:这两篇文章也值得一看(后者数学很重)。
如果您需要比较浮点值,请参见此处:比较浮点值
Single
并且Double
在 .NET 中表示为浮点数,不幸的是,存储这些类型的数字并不精确。使用“单”和“双”数字时,您会得到小的差异。
然而,还有一种选择——.NET 有一种Decimal
更擅长处理这些数字的类型。它仍然不完美(参见http://www.yoda.arachsys.com/csharp/decimal.html - 特别是最后一段),但在表示货币等数量方面会更好。