1

我有这个静态方法,它接收一个双精度并“剪切”它的小数尾部,在点之后留下两位数。几乎一直在工作。我注意到当它收到 2.3 时,它会变成 2.29。0.3、1.3、3.3、4.3 和 102.3 不会发生这种情况。代码基本上将数字乘以 100 使用 modf 将整数值除以 100 并返回它。这里的代码捕获了这个特定的数字并打印出来:

static double dRound(double number) {

    bool c = false;
    if (number == 2.3)
        c = true;


    int factor = pow(10, 2);
    number *= factor;


    if (c) {
        cout << " number *= factor : " << number << endl;
        //number = 230;// When this is not marked as comment the code works well.
    }


    double returnVal;
    if (c){
        cout << " fractional : " << modf(number, &returnVal) << endl;
        cout << " integer : " <<returnVal << endl;
    }


    modf(number, &returnVal);
    return returnVal / factor;
}

它打印出来:

数字 *= 系数:230

小数:1

整数:229

有谁知道为什么会这样,我该如何解决这个问题?谢谢你,祝你周末愉快。

4

2 回答 2

6

记住浮点数不能精确地表示十进制数。2.3 * 100 实际上给出 229.99999999999997。因此modf返回 229 和 0.9999999999999716。

但是,cout默认情况下, 的格式只会显示小数点后 6 位的浮点数。所以 0.9999999999999716 显示为 1。


您可以(大致)使用浮点值表示的误差上限来避免 2.3 错误:

#include <cmath>
#include <limits>
static double dRound(double d) {
   double inf = copysign(std::numeric_limits<double>::infinity(), d);
   double theNumberAfter = nextafter(d, inf);
   double epsilon = theNumberAfter - d;

   int factor = 100;
   d *= factor;
   epsilon *= factor/2;
   d += epsilon;

   double returnVal;
   modf(number, &returnVal);
   return returnVal / factor;
}

结果:http ://www.ideone.com/ywmua

于 2010-10-07T17:36:36.247 回答
0

这是一种不四舍五入的方法:

double double_cut(double d)
{
    long long x = d * 100;
    return x/100.0;
}

即使您想根据小数点后第三位四舍五入,这里有一个解决方案:

double double_cut_round(double d)
{
    long long x = d * 1000;

    if (x > 0)
        x += 5;
    else
        x -= 5;

    return x / 1000.0;
}
于 2010-10-07T18:09:46.940 回答