在学习浮点算法时,我遇到了一些问题,我引述道:“浮点数/双精度数不能精确存储0.1”。
在SO上有一个question指向同一事物,并且公认的答案也非常有说服力。但是我想在自己的计算机上尝试一下,所以我写了下面的程序
double a = 0.1;
if (a == 0.1)
{
Console.WriteLine("True");
}
else
{
Console.WriteLine("False");
}
Console.Read();
,并在控制台上打印True
。令我震惊的是,我已经被其他东西说服了。谁能告诉我浮点算术怎么回事?还是我刚有一台将数字存储为10的计算机?
答案 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#规范允许中间表示使用更高的精度。这意味着有时为字段分配值的简单操作可以更改结果-甚至可以将已经从double
到double
的值进行强制转换。
在您提到的问题中,我们真的不知道如何获得原始值。问题指出:
我有一个名为
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。