1

私はこの静的メソッドを持っています。これは double を受け取り、小数点以下の末尾を「カット」して、ドットの後に 2 桁を残します。ほとんど常に動作します。2.3 を受け取ると、2.29 に変わることに気付きました。これは、0.3、1.3、3.3、4.3、および 102.3 では発生しません。コードは基本的に数値を 100 で乗算し、modf は整数値を 100 で除算して返します。ここで、コードはこの 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

なぜこれが起こっているのか、どうすれば修正できるのか誰か知っていますか? ありがとう、そして素晴らしい週末を。

4

2 に答える 2

6

浮動小数点数は 10 進数を正確に表すことができないことに注意してください。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;
}

小数点以下 3 桁目で丸めたい場合でも、次の解決策があります。

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 に答える