【问题标题】:Understanding C# floating point numbers precision. How does C# stores float numbers? [duplicate]了解 C# 浮点数精度。 C# 如何存储浮点数? [复制]
【发布时间】:2021-09-02 15:48:01
【问题描述】:

在处理浮点数时,我对 C# 中“精度”的实际含义有些怀疑。如果逻辑薄弱并且需要冗长的解释,我会提前道歉。

我知道浮点数(例如10.01F)的精度为 6 到 9 位。所以,假设我们有下一个代码:

float myFloat = 1.000001F;
Console.WriteLine(myFloat);

我在控制台中得到了确切的数字。现在,让我们使用下一个代码:

myFloat = 1.00000006F;
Console.WriteLine(myFloat);

打印了一个不同的数字:1.0000001,尽管这个数字有 9 位数字,这是极限。

这是我的第一个疑问。精度取决于数字本身还是计算机的架构?

此外,数据以位的形式存储在计算机中,在中间,我记得将数字的小数部分转换为位可能会在将数字转换回十进制时导致不同的数字。例如:

(Decimal) 1.0001 -> (Binary) 1.00000000000001101001
(Binary) 1.00000000000001101001 -> (Decimal) 1.00010013580322265625 (It's not the same)

我的逻辑是:也许浮点数在存储时不会丢失信息,也许当数字转换回十进制以显示给用户时,这些信息会丢失。

例如

float myFloat = 999999.11F + 1.11F;

上面的结果应该是:1000000.22。然而,由于这个数字超过了浮点数的精度,我应该看到一个不同的数字,这确实发生了:1000000.25

有 0.03 的差异。为了查看实际结果是否为1000000.22,我做了下一个条件:

if (myFloat == 1000000.22F) {
       Console.WriteLine("Real result = 100000.22");
}

它实际上打印了它:Real result = 100000.22

那么......当将位转换回十进制时会发生信息丢失?或者它也发生在较低级别的计算中,我的例子只是巧合?

【问题讨论】:

标签: c# floating-point storage precision


【解决方案1】:

源代码中的1.000001F被转换为float的值8,388,616•2-23,即1.00000095367431640625。

源代码中的1.00000006F被转换为float的值8,388,609•2-23,即1.00000011920928955078125。

Console.WriteLine 只显示了这些值的一部分;默认情况下,它会将其显示四舍五入到有限的位数。

999999.11F 转换为 15,999,986•2−4,即 999,999.125。 1.11F 转换为 9,311,355•2-23,即 1.11000001430511474609375。当这些使用实数数学相加时,结果为 8,388,609,971,323•2-23。这不能用float 表示,因为float 的小数部分(称为有效数)只能有24 位,所以它作为整数的最大值是16,777,215。如果我们将该有效位除以 219 以将其减少到该限制,我们得到大约 8,388,609,971,323/219 • 2−23•219 = 16,000,003.76•2-4。将该有效位四舍五入为整数产生 16,000,004•2−4。因此,当这两个数字相加时,float 算术将结果四舍五入并产生 16,000,004•2−4,即 1,000,000.25。

那么......当将位转换回十进制时会发生信息丢失?或者它也发生在较低级别的计算中,我的例子只是一个巧合?

将十进制数字转换为浮点数通常会引入舍入误差。

添加浮点数通常会引入舍入误差。

将浮点数转换为精度有限的十进制数通常会引入舍入误差。

【讨论】:

    【解决方案2】:

    当您在代码中写入 1000000.22F 时(编译器必须找到给出的结果最接近十进制数的指数和尾数),以及在转换为十进制以显示时再次发生舍入。

    在实际算术运算中没有任何十进制/二进制类型的舍入,尽管算术运算确实存在与尾数位数有限相关的舍入误差。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-09-16
      • 2011-02-23
      • 1970-01-01
      • 2010-12-19
      • 2021-10-10
      相关资源
      最近更新 更多