3

可能重复:
为什么 C# 中的浮点运算不精确?

为什么浮点运算存在偏差?有什么具体原因吗?输出:160 139

static void Main()
        {
            float x = (float) 1.6;
            int y = (int)(x * 100);
            float a = (float) 1.4;
            int b = (int)(a * 100);
            Console.WriteLine(y);
            Console.WriteLine(b);
            Console.ReadKey();
        }
4

3 回答 3

3

任何分母不是 2 的幂的有理数在表示为二进制时将导致无限位数。这里有 8/5 和 7/5。因此,没有精确的二进制表示为浮点数(除非您有无限的内存)。

1.6 的精确二进制表示是 110011001100110011001100110011001100...
1.4 的精确二进制表示是 101100110011001100110011001100110011...
这两个值都有无限位数(1100 不断重复)。

浮点值的精度为 24 位。因此,任何值的二进制表示都将四舍五入为 24 位。如果将给定值四舍五入为 24 位,您将得到:
1.6:110011001100110011001101(十进制 13421773)-向上舍入
1.4:101100110011001100110011(十进制 11744051)-向下舍入

这两个值的指数均为 0(第一位是 2^0 = 1,第二位是 2^-1 = 0.5 等)。
由于 24 位值中的第一位是 2^23,您可以通过将 24 位值(13421773 和 11744051)除以 23 倍来计算精确的十进制值。
值为:1.60000002384185791015625 和 1.39999997615814208984375。

使用浮点类型时,您始终必须考虑它们的精度是有限的。可以精确写为十进制值的值在表示为二进制时可能会向上或向下舍入。转换为 int 不尊重这一点,因为它会截断给定的值。您应该始终使用 Math.Round 之类的东西。

如果您真的需要有理数的精确表示,则需要一种完全不同的方法。由于有理数是分数,因此您可以使用整数来表示它们。是一个如何实现这一目标的示例。
但是,你不能写 Rational x = (Rational)1.6 那么。您必须编写类似 Rational x = new Rational(8, 5) (或 new Rational(16, 10) 等)的东西。

于 2012-09-16T12:20:38.660 回答
2

This is due to the fact that floating point arithmetic is not precise. When you set a to 1.4, internally it may not be exactly 1.4, just as close as can be made with machine precision. If it is fractionally less than 1.4, then multiplying by 100 and casting to integer will take only the integer portion which in this case would be 139. You will get far more technically precise answers but essentially this is what is happening.

In the case of your output for the 1.6 case, the floating point representation may actually be minutely larger than 1.6 and so when you multiply by 100, the total is slightly larger than 160 and so the integer cast gives you what you expect. The fact is that there is simply not enough precision available in a computer to store every real number exactly.

See this link for details of the conversion from floating point to integer types http://msdn.microsoft.com/en-us/library/aa691289%28v=vs.71%29.aspx - it has its own section.

于 2012-09-15T08:36:32.010 回答
1

浮点类型float(32 位)和double(64 位)具有有限的精度,并且更多的值在内部表示为二进制值。正如你不能在十进制系统中精确地表示 1/7(~ 0.1428571428571428...),在二进制系统中也不能精确地表示 1/10。

但是,您可以使用该decimal类型。它的精度仍然有限​​(但精度很高),但数字 a 在内部以十进制方式表示。因此,像 1/10 这样的值在内部表示完全像 0.1000000000000000000000000000。1/7 对decimal. 但至少你不会因为转换为二进制然后再转换为十进制而损失精度。

考虑使用decimal.

于 2012-09-15T15:29:32.463 回答