C# 浮点运算模糊性

C# 浮点运算模糊性,c#,floating-point,floating,floating-point-precision,C#,Floating Point,Floating,Floating Point Precision,可能重复: 为什么浮点运算存在偏差?有什么具体原因吗? 输出: 160 139 这是因为浮点运算不精确。当您将a设置为1.4时,在内部它可能不完全是1.4,就像机器精度一样接近。如果分数小于1.4,则乘以100并转换为整数将只取整数部分,在本例中为139。你会得到技术上更精确的答案,但本质上这就是正在发生的事情 在1.6情况下的输出中,浮点表示实际上可能比1.6大一点,因此当您乘以100时,总数略大于160,因此整数转换为您所期望的值。事实上,计算机中的精度根本不足以精确地存储每个实数 有关从

可能重复:

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


这是因为浮点运算不精确。当您将
a
设置为1.4时,在内部它可能不完全是1.4,就像机器精度一样接近。如果分数小于1.4,则乘以100并转换为整数将只取整数部分,在本例中为139。你会得到技术上更精确的答案,但本质上这就是正在发生的事情

在1.6情况下的输出中,浮点表示实际上可能比1.6大一点,因此当您乘以100时,总数略大于160,因此整数转换为您所期望的值。事实上,计算机中的精度根本不足以精确地存储每个实数


有关从浮点类型到整数类型的转换的详细信息,请参阅此链接-它有自己的部分。

浮点类型
浮点类型
浮点类型(32位)和
双精度类型
(64位)的精度有限,超过该值的部分在内部表示为二进制值。正如无法在十进制(~0.1428571428571428…)中精确表示1/7一样,1/10也无法在二进制中精确表示

但是,您可以使用
decimal
类型。它的精度仍然有限(无论多么高),但数字a在内部以十进制方式表示。因此,像1/10这样的值在内部表示为与0.10000000000000000000完全相同。对于
十进制
,1/7仍然是个问题。但至少你不会因为转换成二进制再转换回十进制而损失精度


考虑使用
decimal

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

1.6的精确二进制表示是11001100…
1.4的精确二进制表示是101100110011…
两个值的位数都是无限的(1100是无限重复的)

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

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

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

如果你真的需要一个有理数的精确表示,你需要一个完全不同的方法。因为有理数是分数,所以可以用整数来表示它们。这是一个如何实现这一目标的示例。

但是,您不能编写rationalx=(Rational)1.6。您必须编写类似Rational x=new Rational(8,5)(或new Rational(16,10)等)的代码。

这也不适用于
1.3
,但适用于
1.2
1.1
阅读此文章,你好,john!事实并非如此。在这个问题上,重点是存储浮点数。然而,在目前的情况下[1.6(8/5)和1.4(7/5)]不应该有真正的区别。然而,情况显然并非如此。但是整数转换采用浮点的整数部分,不是吗?139.99999999的位数超过了
浮点中所能容纳的位数。因此,在编译器中它可能被舍入到140。我认为舍入和转换是完全不同的事情。我很确定整数转换采用浮点的整数部分,因此产生的值与由编译器通过floor函数获得的值相同如果140->139.9999,那么为什么不对160进行相同的处理,而这两种情况都不涉及导致无限精度浮点数的除法(至少在数学上是如此)@Amber:这是关于表示法的:如果二进制浮点运算被修改成
x=1.4;…(int)(x*100)
生成140,那么必须将x设置为略大于1.4的值(因为不能精确表示1.4)。但是然后,
x=1.4;…(int)((2-x)*100)
将产生59,因为x略大于1.4意味着
2-x
略小于0.6。从数学上讲,让二进制浮点运算像十进制运算一样工作是不可能的。
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();
        }