双打四舍五入

时间:2016-01-27 15:02:44

标签: c++ double rounding c++98

在我的程序中,对于某些双精度存在一些精度(一些正整数,在大多数情况下它应该是x*10^n形式),因此double * precision应该变成整数。

但是我们都知道浮点数是不准确的,所以,例如1.3029515可以保存为1.3029514999999998...,在我的程序中我需要将这样的浮点数写入文件,但是我希望编写此1.3029515而不是1.3029514999999998...之类的内容。

以前在我的程序中只使用了10^n, 0<=n<=8形式的精度,并且我已经用下面的代码达到了想要的结果:

// I have a function for doubles equality check
inline bool sameDoubles(const double& lhs, const double& rhs, const double& epsilon) {
    return fabs(lhs - rhs) < epsilon;
}

inline void roundDownDouble(double& value, const unsigned int& numberOfDigitsInFraction = 6) {
    assert(numberOfDigitsInFraction <= 9);
    double factor = pow(10.0, numberOfDigitsInFraction);
    double oldValue = value;
    value = (((int)(value * factor)) / factor);
    // when, for example, 1.45 is stored as 1.4499999999..., we can get wrong value, so, need to do the check below
    double diff = pow(10.0, 0.0 - numberOfDigitsInFraction);
    if(sameDoubles(diff, fabs(oldValue - value), 1e-9)) {
        value += diff;
    }
};

但是现在,我无法使用相同的技术达到想要的结果,我尝试使用下面的函数,但没有成功:

// calculates logarithm of number with given base
double inline logNbase(double number, double base) {
    return log(number)/log(base);
}

// sameDoubles function is the same as in above case

inline void roundDownDouble(double& value, unsigned int precision = 1e+6) {
    if(sameDoubles(value, 0.0)) { value = 0; return; }
    double oldValue = value;
    value = ((long int)(value * precision) / (double)precision);
    // when, for example, 1.45 is stored as 1.4499999999..., we can get wrong value, so, need to do the check below
    int pwr = (int)(logNbase((double)precision, 10.0));
    long int coeff = precision / pow(10, pwr);
    double diff = coeff * pow(10, -pwr);
    if(sameDoubles(diff, fabs(oldValue - value),  diff / 10.0)) {
        if(value > 0.0) {
            value += diff;
        } else {
            value -= diff;
        }
    }
}

对于1.3029515值和precision = 2000000,此函数返回不正确的1.302951值(表达式(long int)(value * precision)等于2605902而不是2605903)。

我该如何解决这个问题?或者也许有一些聪明的方法可以使这种舍入正确发生?

1 个答案:

答案 0 :(得分:1)

你正在艰难地进行四舍五入。这样做很简单:

double rounding = 0.5;
if (value < 0.0) rounding = -0.5;
value = ((long int)(value * precision + rounding) / (double)precision);

现在不需要其余的代码。