等效表达式可以产生不同的浮点结果吗?

发布于 2024-10-02 07:17:53 字数 335 浏览 4 评论 0原文

这个答案的讨论让我思考浮点数的相等和等价。我知道浮点数并不总是能够准确表示。问题是,使用浮点运算时是否存在数学上等效的表达式会产生不同的结果?你能举个例子吗?

编辑:让我说得更清楚一些。我知道相同的代码使用不同的编译器或不同的机器可能会返回不同的结果。我正在寻找的是两个数学上等价的表达式,我可以在我的Python解释器/C++程序/无论如何中比较它们并得到意想不到的结果。

The discussion to this answer just got me thinking about equality and equivalence of floating point numbers. I am aware that floating point numbers can not always be represented accurately. The question is, are there mathematically equivalent expressions that will yield different results when using floating point arithmetic? Can you provide an example?

Edit: Let me be more clear. I am aware that the same code with different compilers or different machines can return different results. What I am looking for are two mathematically equivalent expressions that I can compare in my Python interpreter/C++ program/Whatever and get an unexpected result.

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

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

发布评论

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

评论(3

逆蝶 2024-10-09 07:17:53

数学上是否等价
会产生不同结果的表达式
使用浮点时的结果
算术?

绝对地。事实上,您应该预料到这种情况会经常发生。

即使相同的代码也可能产生不同的结果结果在不同的机器或编译器上。

你能举个例子吗?

当然。此 Java 代码应该重复产生两个不同的结果:

public strictfp class Test {
    public static void main(String[] args) throws Exception {
        float a = 0.7f;
        float b = 0.3f;
        float c = 0.1f;

        float r1 = ((a * b) * c);
        float r2 = (a * (b * c));

        System.out.println(r1);
        System.out.println(r2);
    }
}

are there mathematically equivalent
expressions that will yield different
results when using floating point
arithmetic?

Absolutely. In fact, you should expect this to happen more often than not.

Even the same code can yield different results on different machines or compilers.

Can you provide an example?

Sure. This Java code should repeatably yield two different results:

public strictfp class Test {
    public static void main(String[] args) throws Exception {
        float a = 0.7f;
        float b = 0.3f;
        float c = 0.1f;

        float r1 = ((a * b) * c);
        float r2 = (a * (b * c));

        System.out.println(r1);
        System.out.println(r2);
    }
}
青芜 2024-10-09 07:17:53

是的,比较例如

x = (a * b) / c;

x = a * (b / c);

这里有一个 C 语言的示例,它演示了这一点:

#include <math.h>
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    double a, b, c, x1, x2;

    a = sqrt((double)rand());
    b = sqrt((double)rand());
    c = sqrt((double)rand());

    x1 = (a * b) / c;
    x2 = a * (b / c);

    printf("a = %.20f\n", a);
    printf("b = %.20f\n", b);
    printf("c = %.20f\n", c);
    printf("x1 = %.20f\n", x1);
    printf("x2 = %.20f\n", x2);
    printf("x1 - x2 = %.20f\n", x1 - x2);

    return 0;
}

对我来说,这给出了以下结果:

$ gcc -O3 -Wall math.c -o math
$ ./math
a = 129.64181424216494065149
b = 16807.00000000000000000000
c = 40282.13093916457728482783
x1 = 54.09073256970189902404
x2 = 54.09073256970190612947
x1 - x2 = -0.00000000000000710543
$ 

(Core i7,gcc 4.0.1,Mac OS X 10.6)

请注意,通常您可能会使用任何给定的表达式得到不同的结果,并且不同的CPU、编译器、编译器开关、数学库等。

Yes, compare e.g.

x = (a * b) / c;

with

x = a * (b / c);

Here's an example in C which demonstrates this:

#include <math.h>
#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    double a, b, c, x1, x2;

    a = sqrt((double)rand());
    b = sqrt((double)rand());
    c = sqrt((double)rand());

    x1 = (a * b) / c;
    x2 = a * (b / c);

    printf("a = %.20f\n", a);
    printf("b = %.20f\n", b);
    printf("c = %.20f\n", c);
    printf("x1 = %.20f\n", x1);
    printf("x2 = %.20f\n", x2);
    printf("x1 - x2 = %.20f\n", x1 - x2);

    return 0;
}

For me this gives the following results:

$ gcc -O3 -Wall math.c -o math
$ ./math
a = 129.64181424216494065149
b = 16807.00000000000000000000
c = 40282.13093916457728482783
x1 = 54.09073256970189902404
x2 = 54.09073256970190612947
x1 - x2 = -0.00000000000000710543
$ 

(Core i7, gcc 4.0.1, Mac OS X 10.6)

Note that in general you may get different results with any given expression and different CPU, compiler, compiler switches, math library, etc.

奢欲 2024-10-09 07:17:53

我会尝试使用乘法和加法:

在伪 C 代码中

float x = 1/7;
float y = x * 4;
float z = x + x + x + x;
if (y != z) {
    printf("oh noes!\n");
}

I'd try with multiplication and addition:

in pseudo-c code

float x = 1/7;
float y = x * 4;
float z = x + x + x + x;
if (y != z) {
    printf("oh noes!\n");
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文