2012-01-06 15 views
3

ネット全体を検索しましたが、私の問題の解決策が見つかりませんでした。私は単にMS Excelのように二重の値を丸める関数を必要とします。ここに私のコードは次のとおりです。MS ExcelのようにC++で二重の値を丸める

#include <iostream> 
#include "math.h" 

using namespace std; 

double Round(double value, int precision) { 
    return floor(((value * pow(10.0, precision)) + 0.5))/pow(10.0, precision); 
} 

int main(int argc, char *argv[]) { 
    /* The way MS Excel does it: 
     1.27815 1.27840 -> 1.27828 
     1.27813 1.27840 -> 1.27827 
     1.27819 1.27843 -> 1.27831 
     1.27999 1.28024 -> 1.28012 
     1.27839 1.27866 -> 1.27853 
    */ 
    cout << Round((1.27815 + 1.27840)/2, 5) << "\n"; // * 
    cout << Round((1.27813 + 1.27840)/2, 5) << "\n"; 
    cout << Round((1.27819 + 1.27843)/2, 5) << "\n"; 
    cout << Round((1.27999 + 1.28024)/2, 5) << "\n"; // * 
    cout << Round((1.27839 + 1.27866)/2, 5) << "\n"; // * 

    if(Round((1.27815 + 1.27840)/2, 5) == 1.27828) { 
         cout << "Hurray...\n"; 
    } 
    system("PAUSE"); 
    return EXIT_SUCCESS; 
} 

私はここにStackOverflowの機能を発見した、その答えは、それが内蔵されたエクセル丸めルーチンと同じように動作することを述べたが、それはしていません。私が何が欠けているか教えてください。

+3

あなたは条件が偽です、あなたは一般的にそのような純粋に浮動小数点値を比較することはできません。 –

+0

実際には丸められた値が必要ですか?または、小数点以下桁数の値を*印字*したいだけですか? –

+0

私はそれ以上の処理のためにそれを必要とします。 –

答えて

2

することはできません。最も一般的なプラットフォーム上で

浮動小数点値は、の概念を持っていません"小数点以下の桁数"。 2.3や8.71のような数字は、正確に表現することはできません。したがって、ゼロ以外の小数点以下の桁数で浮動小数点値を返す関数を要求する意味はありません。このような数値は単には存在しません。

浮動小数点型で行うことができる唯一のことは、最も近い表現可能な近似を計算し、結果を希望の精度で印刷することです。これにより、希望の数値のテキスト形式が得られます。表現を計算するには、あなたがこれを行うことができます:

double round(double x, int n) 
{ 
    int e; 
    double d; 

    std::frexp(x, &e); 

    if (e >= 0) return x; // number is an integer, nothing to do 

    double const f = std::pow(10.0, n); 
    std::modf(x * f, &d);     // d == integral part of 10^n * x 

    return d/f; 
} 

を(またxが既に整数であるかどうかを判断するためにmodfの代わりfrexpを使用することができますあなたはnが負でない、またはそれ以外の意味を定義することも確認する必要があります。 )。負の "精度" のために


また浮動小数点タイプを使用するには、固定を行うことができポイント計算。つまり、すべてをの整数のとして保存しますが、それらをたとえば1/1000の単位として扱います。次のような数字を印刷することができます。

std::cout << n/1000 << "." << n % 1000; 

独自の乗算関数を記述する必要がありますが、期待どおりに加算されます。

0

私はラウンドが魔法を実行することはできません。
1.27828は二重表現では正確ではないので、二重引用符と1.27828を比較することはできません。

+0

どうしたらいいですか?それを文字列に変換しますか? –

+2

さらに処理する必要があり、絶対に正確な精度が必要な場合は、処理を実行する前に100000を掛けて(丸めて)、最終結果を表示する直前に100000で除算することをおすすめしますか? –

2

二重の値を比較するには、比較の範囲を指定する必要があります。ここで結果は「安全」とみなされます。そのためにマクロを使うことができます。ここで

は、使用することができるものの一例である。

#define COMPARE(A, B, PRECISION) ((A >= B - PRECISION) && (A <= B + PRECISION)) 

int main() 
{ 
    double a = 12.34567; 
    bool equal = COMPARE(a, 12.34567F, 0.0002); 

    equal = COMPARE(a, 15.34567F, 0.0002); 
    return 0; 
} 
0

あなたはこのようなので、番号が...何かことを取得するには、小数部なしで数学を行う必要があります。

double dPow = pow(10.0, 5.0); 

    double a = 1.27815; 
    double b = 1.27840; 


    double a2 = 1.27815 * dPow; 
    double b2 = 1.27840 * dPow; 

    double c = (a2 + b2)/2 + 0.5; 

あなたの関数を使用して...あなたが求めているものを意味で

double c = (Round(a) + Round(b))/2 + 0.5; 
1

ありがとうございました!考えられる解決策を考えた後、私は自分のコードの元のRound()関数を0.5の代わりに0.6を値に加えました。

値が "127827.5"(これは正確な表現ではないことがわかります)は "127828.1"になり、最後にfloor()を通って "1.27828"(または1.2782800..001のようなもの)になります。正確に選択された精度でRenan Greinertによって提案されたCOMPAREを使用すると、今は値を安全に比較することができます。私は百二重の値を四捨五入してとExcelが与えるものに結果を比較するよりも、それをテストしてみた

#include <iostream> 
#include "math.h" 
#define COMPARE(A, B, PRECISION) ((A >= B-PRECISION) && (A <= B+PRECISION)) 

using namespace std; 

double Round(double value, int precision) { 
    return floor(value * pow(10.0, precision) + 0.6)/pow(10.0, precision); 
} 
int main(int argc, char *argv[]) { 
    /* The way MS Excel does it: 
     1.27815 1.27840 // 1.27828 
     1.27813 1.27840 -> 1.27827 
     1.27819 1.27843 -> 1.27831 
     1.27999 1.28024 -> 1.28012 
     1.27839 1.27866 -> 1.27853 
    */ 
    cout << Round((1.27815 + 1.27840)/2, 5) << "\n"; 
    cout << Round((1.27813 + 1.27840)/2, 5) << "\n"; 
    cout << Round((1.27819 + 1.27843)/2, 5) << "\n"; 
    cout << Round((1.27999 + 1.28024)/2, 5) << "\n"; 
    cout << Round((1.27839 + 1.27866)/2, 5) << "\n"; 

    //Comparing the rounded value against a fixed one 
    if(COMPARE(Round((1.27815 + 1.27840)/2, 5), 1.27828, 0.000001)) { 
     cout << "Hurray!\n"; 
    } 
    //Comparing two rounded values 
    if(COMPARE(Round((1.27815 + 1.27840)/2, 5), Round((1.27814 + 1.27841)/2, 5), 0.000001)) { 
     cout << "Hurray!\n"; 
    }  

    system("PAUSE"); 
    return EXIT_SUCCESS; 
} 

:ここ

は最終版です。彼らはすべて同じだった。