これは、ストリングからダブルへの変換(例:stdlib.hのatof)を行っていたときに発生していました。私は二重変数0.625に "625"という文字列(二重の小数部分を示す)を入れたいと思っていました。奇妙なことは、私が練習の一環としてそれを入れたときに、結果が不正確な結果になったということです。0.62500000000000011または同様のものです。私は、スタンドアロンの方法でそれを置くときしかし、それは次のコードのように、うまく働いた:C++でdouble型の可変乗算が不正確な値になる
int main(int argc, char **argv) {
string str = "625";
double mask = 0.1;
double frac = 0.0;
for(int i = 0; i < static_cast<int>(str.length()); ++i) {
frac += (str[i] - '0')*mask;
mask *= 0.1;
}
cout << frac << endl;
}
は、上記のコードは正確な結果(0.625)を得ました。私が使用し
string PrintDecimal(string input) {
long int_part = 0;
double frac_part = 0.0;
bool is_positive;
size_t found;
string ret_str;
found = input.find('-');
if(found == string::npos) {
is_positive = true;
}
else {
is_positive = false;
input.erase(found, 1);
}
found = input.find('.');
if(found == string::npos) {
int mask = 1;
char app_char;
for(int i = static_cast<int>(input.length()-1); i > -1; --i) {
int_part += (input[i] - '0')*mask;
mask *= 10;
}
while(int_part != 0) {
app_char = (int_part % 2 == 0) ? '0' : '1';
ret_str.push_back(app_char);
int_part /= 2;
}
if(is_positive == false) {
ret_str.append("-");
}
reverse(ret_str.begin(), ret_str.end());
}
else {
char app_char;
long mask_int = 1;
double mask_frac = 0.1;
string int_part_str = input.substr(0, found);
//string frac_part_str = input.substr(found+1, input.length()-found-1);
string frac_part_str = "0.";
frac_part_str.append(input.substr(found+1, input.length()-found-1));
for(int i = static_cast<int>(int_part_str.length()-1); i > -1; --i) {
int_part += (int_part_str[i] - '0')*mask_int;
mask_int *= 10;
}
//This converting causes 6*0.1 = 0.6000000000009
/*
for(int i = 0; i < static_cast<int>(frac_part_str.length()); ++i) {
frac_part += (frac_part_str[i] - '0')*mask_frac;
mask_frac *= 0.1;
}
*/
frac_part = atof(frac_part_str.c_str()); //This works well.
while(int_part != 0) {
app_char = (int_part % 2 == 0) ? '0' : '1';
ret_str.push_back(app_char);
int_part /= 2;
}
if(is_positive == false) {
ret_str.append("-");
}
reverse(ret_str.begin(), ret_str.end());
ret_str.push_back('.');
found = ret_str.find('.');
while(frac_part != 0.0) {
if(ret_str.length() - found > 64) {
cerr << "Can't express accurately." << endl;
return "Error";
}
frac_part *= 2;
if(frac_part >= 1.0) {
ret_str.push_back('1');
frac_part -= 1;
}
else {
ret_str.push_back('0');
}
}
}
cout << ret_str << endl;
return ret_str;
}
コンパイラのバージョンは、gccのバージョン4.2.1(アップル社は5666をビルド)(ドット3)であった。しかし、次のコードは、不正確な結果(0.62500000000000011)を得ました。 問題の原因となるコードのコメント部分に注意してください。私はこの問題の解決策をあなたのアイデアにお願いします。ありがとう!
浮動小数点の素晴らしい世界へようこそ。 –
私はかなり正確に見えます。それはたったの0.00000000000000011です! –
これで、ほとんど誰もがリードで浮動小数点で噛まれると思います。私が分数なしで1/3を書くように言ったら、0.3333と書いています...そして、ある時点で、やめて(十分であれば)言う必要があります。今、エクササイズとして、1/10(0.1)でもバイナリで同じ操作をしてください。 –