2010-10-07 37 views
1

我有這個靜態方法,它接收到一個雙精度值並「削減」它的分數尾部,在點之後留下兩個數字。工程幾乎一直。我注意到當 它收到2.3它變成2.29。這在0.3,1.3,3.3,4.3和102.3中不會發生。 代碼基本上乘以100乘以modf將整數值除以100並返回它。 這裏代碼捕獲這一個特定號碼,並打印出:modf返回1作爲分數:

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

有人知道爲什麼會發生這種情況,我該如何解決這個問題? 謝謝你,祝你週末愉快。

回答

5

記住浮點數不能準確地表示十進制數。 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

+0

那麼,有沒有更好的方式來「切割」這個尾巴和點後只留下第2位四捨五入沒有? – Matti 2010-10-07 17:43:21

+0

@Matti:查看更新。 – kennytm 2010-10-07 18:09:10

0

這裏是沒有四捨五入的方式:

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

即使你想[R按照小數點後第3位ounding,這裏是一個解決方案:

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

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

    return x/1000.0; 
}