浮点运算太可靠了

时间:2010-04-15 17:13:27

标签: c# floating-point double-precision

我知道在现代计算机系统中执行的浮点运算并不总是与实际算术一致。我正在尝试设计一个小型的C#程序来演示这一点。例如:

static void Main(string[] args)
    {
        double x = 0, y = 0;

        x += 20013.8;
        x += 20012.7;

        y += 10016.4;
        y += 30010.1;

        Console.WriteLine("Result: "+ x + " " + y + " " + (x==y));
        Console.Write("Press any key to continue . . . "); Console.ReadKey(true);
    }

但是,在这种情况下,xy最终相同。

我是否有可能使用类似复杂程序,并且不使用任何真正疯狂的数字来演示浮点运算的不一致性?如果可能的话,我希望避免数学上正确的值超过小数点以外的几个位置。

9 个答案:

答案 0 :(得分:5)

double x = (0.1 * 3) / 3;
Console.WriteLine("x: {0}", x); // prints "x: 0.1"
Console.WriteLine("x == 0.1: {0}", x == 0.1); // prints "x == 0.1: False"

备注:基于此,不要假设浮点运算在.NET中不可靠。

答案 1 :(得分:2)

这是一个基于先前问题的示例,该示例演示了浮点运算不能完全按照您的想法运行。

float f = (13.45f * 20);
int x = (int)f;
int y = (int)(13.45f * 20);
Console.WriteLine(x == y);

在这种情况下,false将打印到屏幕上。为什么?因为执行数学的位置与执行转换的位置相比。对于x,数学在一个语句中执行并存储到f,然后它被转换为整数。对于y,计算的值永远不会在演员表之前存储。 (在x中,计算和演员之间会丢失一些精度,而不是y的情况。

有关浮动数学中特别发生的事情的解释,请参阅此问题/答案。 Why differs floating-point precision in C# when separated by parantheses and when separated by statements?

答案 2 :(得分:2)

我最喜欢的演示归结为

double d = 0.1;
d += 0.2;
d -= 0.3;

Console.WriteLine(d);

输出 0

答案 3 :(得分:1)

尝试制作小数不是.5。

在这里看一下这篇文章

http://floating-point-gui.de/

答案 4 :(得分:0)

尝试汇总非常大和非常小号。小的一个将被消耗,结果将与大数字相同。

答案 5 :(得分:0)

尝试对无理数(例如平方根)或非常长的重复分数执行重复操作。你会很快发现错误累积。例如,计算1000000 * Sqrt(2)与Sqrt(2)+ Sqrt(2)+ ... + Sqrt(2)。

答案 6 :(得分:0)

我现在能想到的最简单的是:

class Test
{
    private static void Main()
    {
        double x = 0.0;

        for (int i = 0; i < 10; ++i)
            x += 0.1;

        Console.WriteLine("x = {0}, expected x = {1}, x == 1.0 is {2}", x, 1.0, x == 1.0);
        Console.WriteLine("Allowing for a small error: x == 1.0 is {0}", Math.Abs(x - 1.0) < 0.001);
    }
}

答案 7 :(得分:0)

我建议,如果你真的感兴趣,你可以看一下讨论浮点数的一些页面中的任何一个,其中一些是血淋淋的细节。你很快就会意识到,在一台计算机中,它们是一种妥协,在范围内折衷准确性。如果您要编写使用它们的程序,您需要了解它们在您不注意时可能出现的局限性和问题。值得你花时间。

答案 8 :(得分:-1)

double精确到~15位数。只需要几个浮点运算就需要更高的精度来真正开始解决问题。