この場合、防ぐことはできません。double
は値 2.11099999999999999999 を正確に表すことができず、2.1109999999999999999と 2.111 を区別する値はありません。
http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.htmlで、知っておくべきことや、さらに多くのことを知ることができます。
丸められた値と丸められていない値を区別する値を表すことができる別の例を使用する場合、次のdouble
ようにすることができます。
#include <iostream>
#include <sstream>
#include <iomanip>
int main() {
std::istringstream iss("2.1109999");
double d;
iss >> d;
std::cout << d << "\n";
std::cout << std::setprecision(10) << d << "\n";
}
出力:
2.111
2.1109999
d
ただし、に格納されている値は正確ではないことに注意してください2.1109999
。
std::cout << std::setprecision(20) << d << "\n";
出力 (私のマシンでは、一部のランタイム ライブラリが 20 sf にまったく出力されないため、異なる場合があります):
2.1109998999999999292
これは、値をdecimal ではなくbinarydouble
で格納するためです。そのため、2 進数の端数のみを表すことができます。2.1109999 は、基本的に 3 分の 1 が終了小数ではないのと同じ理由で、終了 2 進分数ではありません。
したがって、指定された入力をそのまま保持する (つまり、その数値を正確に表す) には 2 つの方法があります。
- に変換せず
double
、文字列のままにしておきます。
- に変換しない
double
でください。代わりに、小数および/または有理数を表すライブラリを見つけるか作成してください。たとえば、GMP ライブラリにはBoost.Rationalmpq_t
があります。