
double型での計算を行うとよく誤差が出るのは知っているのですが
System.out.println(99.98+0.01);
といった簡単な計算ですら数値が狂うのは何故なのでしょうか?-サブ質問1
みなさんは厳密な計算が必要なときどのように処理を行っていますか?-サブ質問2
ちなみに私はできるだけdouble型は使わないことで回避しています。
処理したい有効桁数分10^n倍していってlong型で計算したのち元に戻したりと。
もっとスマートにdouble型だけで正確に計算して使っている方が
いらっしゃいましたらその技を伝授していただけませんか?-メイン質問
わかる範囲でいいのでお答えをお持ちの方がいらっしゃいましたらよろしくお願いします。
No.4ベストアンサー
- 回答日時:
こんにちは
>といった簡単な計算ですら数値が狂うのは何故なのでしょうか?-サブ質問1
2進数だと無限小数(循環小数)になるから、誤差が大きく出てしまうのですね。
>みなさんは厳密な計算が必要なときどのように処理を行っていますか?-サブ質問2
私は分数の概念を使って計算させています。
結局、我々が入力する数値は整数か有限小数ですよね。
それらの四則演算は有理数同士の四則演算なので、結果が整数、有限小数、循環小数のいずれかになります。
これらを正確に表そうとすると、分母と分子が整数の分数として扱うのが良いですね。
これを使うと、例えば
x=1÷3
というようにxに1÷3を入れると、xは0.33333・・・と循環小数になりますが、内部的には3分の1となっているので、
x=x×3
とやると、xは1になってくれます。
>もっとスマートにdouble型だけで正確に計算して使っている方が
>いらっしゃいましたらその技を伝授していただけませんか?-メイン質問
スマートには難しいですね。
分数での処理がスマートかと言われると難しいですね。
No.5
- 回答日時:
>ちなみに私はできるだけdouble型は使わないことで回避しています。
>処理したい有効桁数分10^n倍していってlong型で計算したのち元に戻したりと。
少しだけスマートでいうと、10^n倍したんなら整数になっているはずなのでそのままdoubleで計算しても(有効数値15桁を超えたり、整数で割り切れない割り算をしたりしない限り・・・整数計算なので当然)誤差は出ません。
数字文字列に変換するときは10^n倍したまま、いったん文字列に入れて、下からn桁目の左に小数点を割り込ませるように文字列処理すればいいと思います。
No.3
- 回答日時:
厳密というか、
そういう困ったチャンなことが起きる場合は
BigDecimal使ってこちら側の意図するどおりの桁扱いをするようにしています。
めんどくさいんですけどね。
No.2
- 回答日時:
doubleは8バイトの浮動小数点です。
http://www.jtw.zaq.ne.jp/kayakaya/new/kihon/text …
>もっとスマートにdouble型だけで正確に計算して使っている方が
>いらっしゃいましたらその技を伝授していただけませんか?-メイン質問
10進数に換算すると有効桁数は15桁です。
つまり16桁目以降で誤差がでる可能性があります。
double型ではそれ以上の精度の計算は「不可能」です。
計算で誤差をだしたくないなら
整数型で分母と分子を分け、
無理数や定数は別に計算するような
クラスを作ってはどうでしょうか?
>ちなみに私はできるだけdouble型は使わないことで回避しています。
>処理したい有効桁数分10^n倍していってlong型で計算したのち元に戻したりと。
あまり意味があるものではありません。
結局longも8バイトの整数型なのですから有効桁数に限界があります。
longの限界は9223372036854775807
1桁けずって18桁が有効桁数です。
計算速度を考えればdoubleでやったほうが圧倒的に速いですし、有効桁数が限られている以上、精度には限界があります。
No.1
- 回答日時:
> System.out.println(99.98+0.01);
> といった簡単な計算ですら数値が狂うのは何故なのでしょうか?-サブ質問1
2進数で計算しているからです。99.98、0.01 はいずれも2進数では無限小数になります。
それを有限なコンピュータで計算するのですから、小数点以下のどこかでぶったぎる
必要が生じます。そのための誤差です。
> みなさんは厳密な計算が必要なときどのように処理を行っていますか?-サブ質問2
何をもって厳密と考えるかにもよります。何かの測定値であれば、そもそも最初から
誤差を含んでいますから、10進数での表現と2進数の表現とでどちらが正しいとも
言えないと思います。99ドル98セントといった数値であれば、java.math.BigDecimal等を
使うかもしれません。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
Javaで何パーセント%かを表示...
-
実数からの小数部の取得
-
Javaによる利率計算の実装方法
-
べき乗
-
0dの意味を教えてください
-
System.err. printlnとSystem.o...
-
ループ処理の際、最後だけ","を...
-
オブジェクトの中のプロパティ...
-
動的配列が存在(要素が有る)か...
-
flush()とclose()について
-
IF関数でEmpty値を設定する方法。
-
C#から、C++で作成したdll内の...
-
java キーボード入力された値の...
-
C言語のポインターに関する警告
-
ORA-01858: 数値を指定する箇所...
-
yyyymmddからyyyy/mm/d...
-
EclipseでJava
-
変数を動的に利用するには?
-
Java配列でNullPointerExceptio...
-
Javaで改行などが出来ないのです。
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
実数からの小数部の取得
-
double型変数値の整数部分のみ...
-
0dの意味を教えてください
-
Javaで何パーセント%かを表示...
-
最大値と最小値の求め方
-
newton法のjacobi
-
プログラマーの達人という本の...
-
先に計算したほうがいいのでし...
-
べき乗
-
Javaによる利率計算の実装方法
-
java のfor文について質問です。
-
乱数について
-
x^2+y^2<n^2
-
LU分解を利用した逆行列のプロ...
-
分を表す数値(int型)を、小数...
-
プログラムで指数関数を求めよ...
-
double型の足し算について
-
Javaコンパイルエラー
-
掛け算演算を使わない掛け算
-
乱数のdouble型について
おすすめ情報