【问题标题】:Why Does fmod Produce Different Results?为什么 fmod 会产生不同的结果?
【发布时间】:2015-03-12 06:52:06
【问题描述】:

我在玩下面这段代码

#include <iostream>
#include <cmath>
#include <cstdio>
using namespace std;

int main() {
    double speed = 60.0;
    double distance;
    int a, b, c;
    scanf("%lf %d %d %d", &distance, &a, &b, &c);

    cout << distance <<  " " << a << " " << b << " " << c << endl;
    cout << (fmod((distance*3600)/speed, (a + b + c))) << endl;
    return 0;
}

并注意到,对于以下输入

15.1 1 1 1

它在我的机器上产生这个(不正确的?)结果

15.1 1 1 1
3

但它似乎在 ideone (http://ideone.com/mwMalv) 上产生了这个结果

15.1 1 1 1
0

我意识到“0.1”(在“15”中)不能准确地表示为双精度

http://www.exploringbinary.com/why-0-point-1-does-not-exist-in-floating-point/

但其他使用 gcc 4.8.2 运行此代码的人也可以获得在 ideone 上生成的内容。

我在VMware 6.0.5 build-2443746gcc version 4.8.2 (Ubuntu 4.8.2-19ubuntu1) 上运行Ubuntu 14.04.2 LTS Desktop (32-bit)

什么给了?为什么fmod 在我的机器上的行为与在其他机器上的行为不同(假设编译器相同)?

【问题讨论】:

    标签: c++ gcc g++ double modulus


    【解决方案1】:

    您的计算结果约为fmod(906, 3)。但是,906 可能是 905.9999999999998532 或其他内容,因为错误的值无法准确表示。

    fmod 的结果与 3 相比将给出 2.999999999999999998532,当四舍五入到默认精度 6 时将显示为 3

    要查看详细信息,请在您的 cout 语句中执行 &lt;&lt; setprecision(30)

    检查在每种情况下生成的程序集输出也可能很有启发性。也许编译器正在做不同的事情;或者他们正在做同样的事情,而 FPU 是不同的。

    例如,906 的结果甚至可能以比double 更高的精度完成。在转到fmod 之前更改您的代码以将其存储在double 中可能会或可能不会有所作为。

    【讨论】:

    • 感谢您分享您对此的详细想法。我按照你的建议做了,输入了&lt;&lt; setprecision(30),得到了2.99999999999997868371792719699。我还更改了代码以将计算存储在double 之前 移动到fmod 但得到了相同的结果。不过,我不确定如何检查程序集输出。
    • 在 gcc 中使用 -S 开关编译。 ,它会输出汇编
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-10
    • 2017-02-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多