计算机是否已开始正确存储0.1?

时间:2018-07-01 07:51:37

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

在学习浮点算法时,我遇到了一些问题,我引述道:“浮点数/双精度数不能精确存储0.1”。

在SO上有一个question指向同一事物,并且公认的答案也非常有说服力。但是我想在自己的计算机上尝试一下,所以我写了下面的程序

double a = 0.1;

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

Console.Read();

,并在控制台上打印True。令我震惊的是,我已经被其他东西说服了。谁能告诉我浮点算术怎么回事?还是我刚有一台将数字存储为10的计算机?

1 个答案:

答案 0 :(得分:7)

您的程序仅检查编译器是否两次以相同的方式逼近0.1。

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

您的代码已有效地编译为此:

category_id

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

有时候您会看到一些非常奇怪的效果。尽管double a = 0.1000000000000000055511151231257827021181583404541015625; if (a == 0.1000000000000000055511151231257827021181583404541015625) { Console.WriteLine("True"); } else { Console.WriteLine("False"); } 被定义为64位IEEE-754数字,但是C#规范允许中间表示使用更高的精度。这意味着有时为字段分配值的简单操作可以更改结果-甚至可以将已经从doubledouble的值进行强制转换。

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

  

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

我们不完全知道如何为它分配0.1值,这一细节很重要。我们知道该值不会精确地为 0.1,那么涉及哪种近似值?例如,考虑以下代码:

x

x的值大约为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); } } 最接近0.1的值”并不完全相同。在这种情况下,它恰好小于0.1-该值恰好是0.099999999999999999997779553950749686919152736663818359375,不等于0.1000000000000000055511151231257827021181583404541015625 ...所以比较打印为False。