0

任何人都可以解释这种怪异:

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
4

4 回答 4

2

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无论如何都无法适应。

于 2009-11-12T12:06:30.893 回答
1

这是由于浮点数在内存中表示方式的限制。阅读维基百科页面以了解完整的内幕——这不是错误,也不是 .net 特有的东西。

编辑:这两篇文章也值得一看(后者数学很重)。

于 2009-11-12T12:06:50.557 回答
0

如果您需要比较浮点值,请参见此处:比较浮点值

于 2009-11-12T12:07:52.893 回答
0

Single并且Double在 .NET 中表示为浮点数,不幸的是,存储这些类型的数字并不精确。使用“单”和“双”数字时,您会得到小的差异。

然而,还有一种选择——.NET 有一种Decimal更擅长处理这些数字的类型。它仍然不完美(参见http://www.yoda.arachsys.com/csharp/decimal.html - 特别是最后一段),但在表示货币等数量方面会更好。

于 2009-11-12T12:12:22.417 回答