![](http://oshiete.xgoo.jp/images/v2/pc/qa/question_title.png?5a7ff87)
Java初心者です。
よろしくお願いいたします。
double型の変数に数値を代入して、足し算をするプログラムを組んだとして、
例えば、
10.5 と 1.5 を 代入すると、答えは 12.0 になりました。
問題ないです。
しかし、
数値をいろいろ変更してみると、おかしな答えになるケースがある事を発見しました。
例えば、
4.1 と 3.8 を代入すると、 7.8999999999999995 となったり、
1.8 と 2.1 を代入すると、 3.9000000000000004 となったりするのです。
なぜそうなるのか、よくわかりません。
わかり易い解説をして頂けると嬉しく思います。
よろしくお願いいたします。
No.4ベストアンサー
- 回答日時:
次のJavaプログラムを実行してみてください。
class Q7461149 {
public static void main(String[] args) {
double d1 = 10.5;
double d2 = 1.5;
System.out.println(d1);
System.out.println(d2);
System.out.println(d1 + d2);
System.out.println(Double.toHexString(d1));
System.out.println(Double.toHexString(d2));
System.out.println(Double.toHexString(d1 + d2));
}
}
----------------------------------------
10進数の 10.5 をdouble型変数に格納したとき,
その変数の内部データは 16進文字列(HexString)書式で 0x1.5p3,
これは2進表記で (1.0101)2 × 2の3乗を表しています。
(1+ 1/4 + 1/16)×8 = 10.5ということです。
10進数の 1.5 をdouble型変数に格納したとき,
その変数の内部データは 16進文字列(HexString)書式で 0x1.8p0,
これは2進表記で (1.1000)2 × 2の0乗を表しています。
(1+ 1/2)×1 = 1.5ということです。
両者の和は,指数を2の3乗に統一することで計算でき,
{(1.0101)2 + (0.0011000)2}×2の3乗 = (1.1)2 × 2の3乗です。
10進数の10.5 と 10進数の1.5,どちらも,
1,1/2,1/4,1/8,1/16 といった有限長の2進数の組合せで
びったり正確に表現できる数だったということです。
----------------------------------------
次に d1,d2 の値を次のように変更してみます。
double d1 = 4.1;
double d2 = 3.8;
10進数の 4.1 をdouble型変数に格納したとき,
その変数の内部データは 16進文字列(HexString)書式で
0x1.0666666666666p2 となります。これは2進表記で
(1.0000 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110 0110)2 × 2の2乗
となる「循環無限小数」であり,同パターンの繰り返しがどこまでも続きます。
つまり10進数の 4.1 は,1,1/2,1/4,1/8,1/16 …といった
有限長の2進数の組合せでは,ぴったり正確に表現できないのです。
10進数の 3.8 も同様であり,d1+d2 に誤差が生じる理由はこれです。
----------------------------------------
このような例を「おかしな答え」だとお感じになるのなら,
double型の変数の中身全体をそのまま出力するのではなく,
小数点以下の桁数を若干短くして出力してみてください。
例えば次のように書くと,
小数点以下の表示を15けたまでに限定できます。
System.out.printf("%.15f", d1 + d2);
No.5
- 回答日時:
double 型は IEEE754の倍精度浮動小数点 という形式で
数値を保持します。この形式は、10進で書いたリテラルの実数値を
誤差なく保持できない場合が多々あるのでこうなります。
http://ja.wikipedia.org/wiki/IEEE_754
これは Java というよりプログラミングの基本ですが、
不思議なことに、ちゃんと勉強している人がなぜか非常に少ないんですよね。
頑張ってください。
No.3
- 回答日時:
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- Visual Basic(VBA) Excel のユーザー定義関数でソルバーが動作しない 1 2022/09/05 19:51
- 大学受験 数学1の問題 「おさえておきたい基礎100Gakken」より 3 2023/04/11 23:28
- 数学 数2Bの数列の問題です。 自分は、 まず数列 an=ar^(n-1)と置き こちらの問題の、y= の 1 2022/07/07 16:26
- 統計学 統計検定2級の過去問について 1 2023/01/04 16:40
- Excel(エクセル) 電卓は正しいのに エクセルで計算させると間違った答えです。なぜ? 7 2022/08/11 07:04
- 大学受験 合同式 1 2022/09/03 12:37
- C言語・C++・C# C言語初心者 構造体 課題について 1 2023/03/10 19:30
- 数学 数学1の問題がわかりません。 次の関数において、頂点の座標と、[]内のxの値に対するyの値を求めよ。 3 2023/02/13 00:36
- 数学 高校数学 初歩的ですが。 数学で、〜〜をみたす○○を求めよ。 と問われた時、 求める〇〇は〜〜の必要 6 2022/03/29 10:10
- 確定申告 確定申告の「更生の請求」について 6 2022/10/24 19:07
関連するカテゴリからQ&Aを探す
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
0dの意味を教えてください
-
モンテカルロ法を用いた球の体...
-
Javaで何パーセント%かを表示...
-
実数からの小数部の取得
-
べき乗
-
最大値と最小値の求め方
-
double型変数値の整数部分のみ...
-
java プログラム 範囲を指定し...
-
Javaプログラムのフローチャー...
-
osamuyさん、では「今まで入力...
-
小数点以下の切捨てにつきまして
-
double型の足し算について
-
javaの課題。。
-
javaでC++のdefine文に相当する...
-
矩形法プログラムの計算値と計...
-
JSPやサーブレットでSystem.out...
-
System.err. printlnとSystem.o...
-
ページング
-
ダブルクォーテーションのrepla...
-
C言語のポインターに関する警告
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
べき乗
-
実数からの小数部の取得
-
Javaで何パーセント%かを表示...
-
0dの意味を教えてください
-
最大値と最小値の求め方
-
double型変数値の整数部分のみ...
-
Javaによる利率計算の実装方法
-
doubleで入力するには?
-
doubleとintの違い
-
JAVAのプログラムで、2乗計算...
-
double型の足し算について
-
掛け算演算を使わない掛け算
-
実数 2.0 に対して int(2.0) ==...
-
Javaコンパイルエラー
-
java のfor文について質問です。
-
C# ToStringでの数字桁揃えの仕方
-
java プログラム 範囲を指定し...
-
Javaのeval関数処理
-
printfでのエラーがわからない...
-
数値積分について
おすすめ情報