modf以小数形式返回1:

1 c++ double integer fractions fmodf

我有这个静态方法,它接收一个double并"切割"它的小数尾部,在点之后留下两位数.工程几乎所有的时间.我注意到当它收到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;
}
Run Code Online (Sandbox Code Playgroud)

打印出来:

数字*=因子:230

分数:1

整数:229

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

ken*_*ytm 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;
}
Run Code Online (Sandbox Code Playgroud)

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