浮点运算太可靠了

发布于 2024-08-28 16:08:05 字数 541 浏览 14 评论 0原文

我知道现代计算机系统中执行的浮点算术并不总是与实际算术一致。我正在尝试设计一个小型 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 最终是相等的。

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

I understand that floating point arithmetic as performed in modern computer systems is not always consistent with real arithmetic. I am trying to contrive a small C# program to demonstrate this. eg:

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);
    }

However, in this case, x and y are equal in the end.

Is it possible for me to demonstrate the inconsistency of floating point arithmetic using a program of similar complexity, and without using any really crazy numbers? I would like, if possible, to avoid mathematically correct values that go more than a few places beyond the decimal point.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(9

情栀口红 2024-09-04 16:08:05
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 中的浮点运算不可靠。

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"

Remark: based on this don't make the assumption that floating point arithmetic is unreliable in .NET.

み零 2024-09-04 16:08:05

这是一个基于先前问题的示例,该示例演示了浮点算术的计算结果并不完全按照您的想象。

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

在这种情况下,false 会打印到屏幕上。为什么?因为数学的执行位置与 int 类型转换的执行位置不同。对于 x,数学在一个语句中执行并存储到 f,然后将其转换为整数。对于 y,计算值在转换之前不会被存储。 (在 x 中,计算和转换之间会丢失一些精度,而 y 则不然。)有关

浮点数学中具体发生的情况背后的解释,请参阅此问题/答案。 为什么不同C# 中用括号分隔和用语句分隔时的浮点精度?

Here's an example based on a prior question that demonstrates float arithmetic not working out exactly as you would think.

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

In this case, false is printed to the screen. Why? Because of where the math is performed versus where the cast to int is happening. For x, the math is performed in one statement and stored to f, then it is being cast to an integer. For y, the value of the calculation is never stored before the cast. (In x, some precision is lost between the calculation and the cast, not the case for y.)

For an explanation behind what's specifically happening in float math, see this question/answer. Why differs floating-point precision in C# when separated by parantheses and when separated by statements?

蔚蓝源自深海 2024-09-04 16:08:05

我最喜欢的演示可以归结为“

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

Console.WriteLine(d);

输出是不是 0”。

My favourite demonstration boils down to

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

Console.WriteLine(d);

The output is not 0.

つ低調成傷 2024-09-04 16:08:05

尝试使其小数点不是 0.5。

在这里查看这篇文章

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

Try making it so the decimal is not .5.

Take a look at this article here

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

夜空下最亮的亮点 2024-09-04 16:08:05

尝试将非常大数和非常小数相加。小的将被消耗,结果将与大的相同。

try sum VERY big and VERY small number. small one will be consumed and result will be same as large number.

云仙小弟 2024-09-04 16:08:05

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

Try performing repeated operations on an irrational number (such as a square root) or very long length repeating fraction. You'll quickly see errors accumulate. For instance, compute 1000000*Sqrt(2) vs. Sqrt(2)+Sqrt(2)+...+Sqrt(2).

执着的年纪 2024-09-04 16:08:05

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

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);
    }
}

The simplest I can think of right now is this:

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);
    }
}
浅笑依然 2024-09-04 16:08:05

我建议,如果您真的感兴趣,请看一下讨论浮点数的许多页面中的任何一个,其中一些页面非常详细。您很快就会意识到,在计算机中,它们是一种折衷方案,以精度换取范围。如果您要编写使用它们的程序,您确实需要了解它们的局限性以及如果您不小心可能会出现的问题。这将是值得您花时间的。

I suggest that, if you're truly interested, you take a look any one of a number of pages that discuss floating point numbers, some in gory detail. You will soon realize that, in a computer, they're a compromise, trading off accuracy for range. If you are going to be writing programs that use them, you do need to understand their limitations and problems that can arise if you don't take care. It will be worth your time.

℉服软 2024-09-04 16:08:05

double 精确到约 15 位数字。您需要更高的精度才能真正开始仅通过几个浮点运算来解决问题。

double is accurate to ~15 digits. You need more precision to really start hitting problems with only a few floating point operations.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文