【问题标题】:Have computers started storing 0.1 correctly?计算机是否开始正确存储 0.1?
【发布时间】:2018-12-09 19:26:03
【问题描述】:

在学习浮点运算时,我遇到了一些事情,我引用:'a float/double can't store 0.1 exact"。

在 SO 上有一个 question 指向同样的事情,并且接受的答案也非常有说服力。但是我想在我自己的电脑上尝试一下,所以我写了下面的程序

double a = 0.1;

if (a == 0.1)
{
    Console.WriteLine("True");
}
else
{
    Console.WriteLine("False");
}

Console.Read();

控制台打印True。令人震惊,因为我已经对其他事情深信不疑。谁能告诉我浮点运算发生了什么?或者我只是有一台将数值存储为以 10 为底的计算机?

【问题讨论】:

  • 鉴于它的存储不准确以相同的方式两次你写它为什么不会他们是平等的?
  • @jonrsharpe:我完全同意,当你以正确的方式思考它时,它就会变得显而易见。但我认为,如果你不习惯思考到底发生了什么,这是一个合理的问题。
  • @jonrsharpe 我提到的问题是在做同样的事情,如果我错了,请纠正我。
  • 我在我的电脑上得到了正确的结果。您使用的是调试还是发布? Debug 和 Release 的结果是否相同?有一些微处理器有内部错误,会给出错误的结果。 Debug 使用模拟器来执行数学运算,而 Release 使用 micro 内部的浮点算术单元。我见过两者都失败了。某些 PC 有补丁来修复 FPU 中的错误,并且补丁可能安装错误,具体取决于 PC 上安装的 Micro。答案应始终为 TRUE,错误除外。

标签: c# floating-point precision ieee-754


【解决方案1】:

您的程序只检查编译器是否以相同的方式两次逼近 0.1,它确实如此。

a 的值不是 0.1,并且您没有检查它是否 0.1。您正在检查“最接近 0.1 的可表示值”是否等于“最接近 0.1 的可表示值”。

您的代码被有效地编译为:

double a = 0.1000000000000000055511151231257827021181583404541015625;

if (a == 0.1000000000000000055511151231257827021181583404541015625)
{
    Console.WriteLine("True");
}
else
{
    Console.WriteLine("False");
}

...因为 0.1000000000000000055511151231257827021181583404541015625 是最接近 0.1 的 double 值。

您仍然可以看到一些非常奇怪的效果。虽然 double 被定义为 64 位 IEEE-754 数字,但 C# 规范允许中间表示使用更高的精度。这意味着有时将值分配给字段的简单行为可能会改变结果 - 甚至将已经是 double 的值转换为 double

在你提到的问题中,我们并不真正知道原始值是如何获得的。问题指出:

我有一个名为x 的双变量。在代码中,x 被赋值为 0.1

我们不知道它是如何被赋值为 0.1 的,这个细节很重要。我们知道该值不会恰好 0.1,那么涉及到什么样的近似值?例如,考虑以下代码:

using System;

class Program
{
    static void Main()
    {
        SubtractAndCompare(0.3, 0.2);
    }

    static void SubtractAndCompare(double a, double b)
    {
        double x = a - b;
        Console.WriteLine(x == 0.1);
    }
}

x 的值大约为 0.1,但它与“最接近 0.1 的 double 值”的近似值并不完全相同。在这种情况下,恰好是略小于0.1 - 该值是恰好0.09999999999999997779553950749686919152736663818359375,这不等于0.1000000000000000055511151231257827021181583404541015625 ...这样的比较输出false P>。

【讨论】:

  • 谢谢,对了,我提到的问题不也是这样吗?
  • @Imad:在您链接到的问题中,OP 说“在代码中,x 被赋值为 0.1”,但从未显示这是如何发生的。如果它是算术的结果(例如,从 0.9 中减去 0.8),那么它的值很可能接近 0.1,但不是相同的近似值。我们无法从问题中真正看出。
  • @Imad:我提供了一个例子来帮助澄清。
猜你喜欢
  • 1970-01-01
  • 2020-06-19
  • 1970-01-01
  • 2017-02-28
  • 1970-01-01
  • 2015-08-01
  • 2012-08-07
  • 2018-03-30
  • 1970-01-01
相关资源
最近更新 更多