-2

私は c++ でコーディングを始めたばかりですが、MATLAB と MySql の経験はかなりあります。いくつかの複合数を計算しようとしているため、精度が重要です。倍数を使用してこれを実行しようとしましたが、何らかの理由で有効数字 7 桁 (float と同じ) の精度しか得られませんでした。long double を使用して計算を試みましたが、それでも 7 sf の精度しか得られません。

double を正しく初期化していませんか? 私はそれらが標準ライブラリの一部だと思った?? どんな助けでも大歓迎です。以下のコードは、計算に使用されるコードの主要部分を示しています (残りは主にデータのロードまたはデバッグです)。


アップデート

コードのサンプルを次に示します (マイナスのデータ読み取り)。最初の 5 つの値を入力しました。計算は ( EXPECTED OUTPUT ) Excel で計算され、まったく同じ入力を使用する必要があります。

0
-1.09526
4.364551963
2.745835774
3.029002506

以下のコードが与えるもの ( ACTUAL OUTPUT ):

0
-1.095260000
4.3591394642
2.7340763329
3.0179393198

コード:

#include <fstream>
#include <iostream>
#include <sstream>
#include <string>
#include <vector>


using namespace std;

int main(){

std::vector<double> compoundedcalculation; // pre-allocating for the compounded calculations
std::vector<double> dailycompound; // pre-allocating for daily compoundvalue
compoundedcalculation.insert(compoundedcalculation.end(), 0.0); // setting the first value as 0

double dailycompoundval[] = {0,-1.09526,5.46038,-1.61801,0.283089};
dailycompound.assign(dailycompoundval,dailycompoundval+5);
double indCC;

for (int n = 0; n < 5 ;n++)
    {   
    indCC = ((((1+((compoundedcalculation.at(n))/1000))*(1+((dailycompound.at(n))/1000)))-1)*1000);

    printf(" %.17g  \n", indCC);


    compoundedcalculation.insert(compoundedcalculation.end(), indCC ); 
    }
return 0;
}

ありがとうございます。


更新 2:

予想結果と実際の結果の両方で、複利計算に同じ式が使用されます。

複利合計 = ((1+(日次レート/10000))*(1+(前回の複利合計/10000)))

1 日の料金は次のとおりです。

1 日目: 0 2 日目: -1.09526 3 日目: 5.46038 4 日目: -1.61801 5 日目: 0.283089

4

2 に答える 2

4

doubleは IEEE 64 ビット float であるため、有効な 15 桁から 17 桁の 10 進数が格納されます。このために特別なことをする必要はありません。あなたの問題は、あなたが示していない画面に印刷する方法です。デフォルトでは、値は有効数字 6 桁に丸められるため、次のように増やす必要があります。

cout.precision(17);
cout << x;

また

printf("%.17g", x);

出力方法によって異なります。

更新:高精度の計算機を使用して手動で計算すると、次のようになります。

n = 0: ((1 + 0/1000)*(1 + 0/1000) - 1)*1000
        == 0
n = 1: ((1 + 0/1000)*(1 + -1.09526/1000) - 1)*1000
        == -1.09526
n = 2: ((1 + -1.09526/1000)*(1 + 5.46038/1000) - 1)*1000
        == 4.3591394642012
n = 3: ((1 + 4.3591394642012/1000)*(1 + -1.61801/1000) - 1)*1000
        == 2.734076332956727816388
n = 4: ((1 + 2.734076332956727816388/1000)*(1 + 0.283089/1000) - 1)*1000
        == 3.017939319891748203508813462532

コードを実行すると、同じ結果が得られます。

 0  
 -1.0952599999999999  
 4.3591394642012  
 2.7340763329567279  
 3.0179393198917484  

ただし、1000 を 10000 に置き換えると、「期待される結果」が得られます。

 0  
 -1.0952599999999999  
 4.3645219464201199  
 2.7458057624046663  
 3.0289724931454134  

あなたの質問に答えているようです。

于 2013-01-16T11:31:49.503 に答える
1

Visual Studio では、doubleIEEE754 倍精度です。これには、53 ビットのバイナリ精度、または約 15 ~ 16 の 10 進数の有効数字があります。

おそらく、値を出力している診断コードは 7 桁の精度でしか出力されません。または、デバッガー ビューに 7 桁の精度しか表示されません。

つまり、問題は基になるデータ型ではなく、そのデータの表示方法にあります。

更新 1

あなたのコメントは、倍精度値の計算が単精度で実行されていると信じていることを示しています。デフォルトでは、そうはなりません。への呼び出しで浮動小数点の精度制御を変更した場合に発生する可能性があります_controlfp。ただし、浮動小数点コントロールがデフォルト値に設定されている場合、倍精度値の演算は単精度に丸められません。

更新 2

Excel の計算で別の計算が実行されています。C++ プログラムからの出力はコードと一致します。-1.09526コードに一致する最初のゼロ以外の値の出力。コードは値が であるべきだと言っているからですdailycompoundval[1]。Excel コードからの対応する値は-1.095231419であるため、C++ コードとは一致しません。

言い換えれば、質問はニシンです。ここには丸めの問題はありません。この問題は、コードの 2 つの異なるバージョン間の不一致に完全に起因しています。

アップデート 3

あなたの C++ コードは、最新の更新プログラムの式と一致しません。コードでは乗法係数 1000 を使用していますが、式では係数 10000 を使用しています。

于 2013-01-16T11:30:46.707 に答える