C++ Visual Studio Express 2012 中的舍入错误

Rounding error in C++ Visual Studio Express 2012

我在尝试用 C++ 编写自己的舍入函数时遇到了一个非常奇怪的功能。

以下两个函数的输出都是 0.000。

double round ( double x, int y)
{
    double value = 0;

    value = floor(x*pow(10, y) + x>=0?0.5:-0.5)/pow(10, y);

    return value;
}

double round3(double x)
{
    double value = 0;

    value = floor(x * 1000 + x>=0?0.5:-0.5) / 1000;

    return value;
}

但是此函数会产生正确的输出,四舍五入到小数点后 3 位。

double round(double x)
{
    double value = 0;

    if (x >= 0){
        value = floor( x*1000 + 0.5 )/1000;
    }
    else{
        value = floor( x*1000 - 0.5 )/1000;
    }
    return value;
}

谁能告诉我为什么会这样?

三元运算符?:的优先级比较低,this

x * 1000 + x>=0?0.5:-0.5

相当于:

(x * 1000 + x>=0)?0.5 :-0.5

结果为 0.5-0.5

前两个有 operator precendence 个错误,例如(x * 1000 + x>=0?0.5:-0.5) / 1000 被计算为 (((x * 1000 + x) >= 0) ? 0.5 : -0.5) / 1000,因此当 x 为正时为 0.0005,当 x 为负时为 -0.0005。

还要记住,"rounding" 双打是一件棘手的事情...第 15 位或第 16 位通常会有错误,是否因为 "mathematically perfect" 运算结果已执行不能在 double 变量中准确表示,或者由于中间值或数学函数(如 pow 中的近似值,因此您可能会发现您认为是 "n.5" 的值有时向上舍入,有时向下舍入。如果对此感到困惑,也许阅读 What Every Computer Scientist Should Know About Floating-Point Arithmetic.