プログラム上で計算するときに丸め誤差が発生し、困っています。
丸め誤差が発生している計算は
-0.004+0.006+0.002
なのですが、
-0.004+0.006+0.002=0
となるところが、 =8.47E-09
となってしまっています。
オーダーの異なる計算ではないにもかかわらず、どうして誤差が発生するのかが理解できず困っています。
上の数値(左辺の方)の算出は、10^(-1)のオーダーの数値から計算されています。
多分、浮動小数点を使っているからだろうと考えているのですが、どのように解消したらよろしいでしょうか?
固定小数点を用いると、浮動小数点より誤差が少ないとありましたが、Cで固定小数点を用いる方法もわからないです。
よろしくお願いします。
No.2ベストアンサー
- 回答日時:
コンピュータは2進数なので仕方がないです。
10進数では有限小数であっても、2進数に変換すると循環小数等になってしまい、正確に計算することはできません。
試しに0.1を2進数に変換してみると一目瞭然。
これはC言語やそのほか多くのプログラミング言語の制限事項です。
COBOLとかではきちんと計算できます。(だから昔から小数をきちんと計算する必要のある銀行系のシステムにCOBOLが多いのです。)
数値を文字列として読み込んで、計算ロジックは自作するのが一番簡単です。
確かに、基数変換をしてみると、0.1は2進数で表せませんでした。
このような制限があるとは知らず、プログラミングしていたので、それを解消する、また別の方法を再考します。
回答ありがとうございます。
No.6
- 回答日時:
命題の真偽について
「浮動小数点は最後の数が0もしくは5で終わる数値以外は常に誤差が生じます」
0は間違いとして
5で終わる数値以外は常に誤差が生じます
という命題が真でもその裏命題の
5で終わる数値は常に誤差が生じない
が成り立たつとは限りませんよ
0.05に誤差があっても本命題には違反しません
No.5
- 回答日時:
「上の数値(左辺の方)の算出は、10^(-1)のオーダーの数値から計算されています。
」というのはどういう意味でしょうか? 本当にそうなら, この数値が得られた時点で (ある程度) 桁落ちは避けられないと思うのですが.
実際問題として浮動小数を使う限りこのような誤差の発生は避けられないし, 「誤差が発生する」ことは前提にしないとダメ.
解析を行うためのプログラミングをしているのですが、解析を行う前の準備段階での誤差でしたので、解消を考えてました。
浮動小数点を用いる限り丸め誤差を避けられないのは仕方のないことだとは思うのですが、どうしても誤差を避けたく思っていました。
この誤差の評価も含めて、解析したいと考えています。
回答ありがとうございました。
No.4
- 回答日時:
【補足依頼】
質問者さんに確認したいことがあります。
「-0.004+0.006+0.002」は0.004になると思いますが実際にはどんなソースコードで計算されていますか?ソース開示出来る場合は開示をお願いします。
あと質問にある「オーダー」というのは基数とか小数点の位置を言っているのでしょうか,すいません補足説明が可能であればお教え下さい。
【アドバイス】
小数の桁数が3桁くらいなら,回答者#1さんの回答にある整数計算というのでこの計算はできます。
-0.004は1000倍して-4,0.006は1000倍して6,0.002は1000倍して2
あとは整数の足し算 -4+6+2=4
最後に小数に戻すために足し算した値を1000で割り0.004と答えが出ます。
この方法の問題点は(小数を含む値 × 10^小数桁数)が整数型に収まる必要があります。また,その値を使った計算もオーバーフローしない事が条件となります。
No.1
- 回答日時:
浮動小数点は最後の数が0もしくは5で終わる数値以外は常に誤差が生じます
0.625だと誤差はないのですが
0.63だと浮動小数点では誤差が生じます
Cで固定小数点(10進ライブラリ)を扱えなくはないのですが
(そういうライブラリを手に入れる必要あり)
計算が非常に面倒です
(以下、あくまでも例です)
例)
decimal a;
a = toDecimal(0.630);
decimal b;
b = toDecimal(0.12);
decimal c;
c = addDecimal(a, b);
同様の事がC++であれば、クラスを使えるので
だいぶ簡単になります
(こちらもライブラリを手に入れる必要あり)
decimal a = 0.630;
decimal b = 0.12;
decimal c = a+b;
で、結論ですが、そもそもどんな計算をしたいのかがわからないので
勝手に推測して答えます
1.ゲームを作成する等で計算したい
そもそも誤差が出るのを考慮して計算する必要がある
if (a == 0.12)は駄目で、
if (abs(a-0.12) < 0.0001)のようにする
2.金額の計算に使う
小数点はやめて、整数で計算すべき
(金利などで小数が必要であれば、値を100倍、1000倍などして計算する等)
有限要素解析を行う場合の、有限要素行列作成のために計算される必要がある定数に関しての計算において、このような誤差が発生しました。
解析的に計算される値に対して、丸め誤差の発生を承知して解析を行うことに対して、かなり抵抗感があり、ここでの誤差を解消できるかを考えていました。
計算コストはできるだけ減らしたいのこともあり、丸め誤差の発生については再考します。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
関連するカテゴリからQ&Aを探す
おすすめ情報
- ・漫画をレンタルでお得に読める!
- ・街中で見かけて「グッときた人」の思い出
- ・「一気に最後まで読んだ」本、教えて下さい!
- ・幼稚園時代「何組」でしたか?
- ・激凹みから立ち直る方法
- ・1つだけ過去を変えられるとしたら?
- ・【あるあるbot連動企画】あるあるbotに投稿したけど採用されなかったあるある募集
- ・【あるあるbot連動企画】フォロワー20万人のアカウントであなたのあるあるを披露してみませんか?
- ・映画のエンドロール観る派?観ない派?
- ・海外旅行から帰ってきたら、まず何を食べる?
- ・誕生日にもらった意外なもの
- ・天使と悪魔選手権
- ・ちょっと先の未来クイズ第2問
- ・【大喜利】【投稿~9/7】 ロボットの住む世界で流行ってる罰ゲームとは?
- ・推しミネラルウォーターはありますか?
- ・都道府県穴埋めゲーム
- ・この人頭いいなと思ったエピソード
- ・準・究極の選択
- ・ゆるやかでぃべーと タイムマシンを破壊すべきか。
- ・歩いた自慢大会
- ・許せない心理テスト
- ・字面がカッコいい英単語
- ・これ何て呼びますか Part2
- ・人生で一番思い出に残ってる靴
- ・ゆるやかでぃべーと すべての高校生はアルバイトをするべきだ。
- ・初めて自分の家と他人の家が違う、と意識した時
- ・単二電池
- ・チョコミントアイス
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
ExcelでPC(パソコン)によって...
-
計算の丸め誤差の解消について
-
c languageで 簡単な質問があ...
-
三菱シーケンサ(Aシリーズ)で...
-
教えて小数点の比較!(C言語)
-
演算について
-
除算を使わずに10で割りたい。
-
VB.net Double と...
-
MATLABでの行列の全要素の和
-
計算機誤差
-
有効数字について 以前質問をし...
-
0.1の10000回の累積
-
”/”を使わずに割り算したいんで...
-
計算精度(限りなくゼロに近く)
-
ラズベリーパイ>MM-TXS03で温度...
-
スーパーコンピュータの処理速...
-
java 実数の割り算
-
Log関数に関する質問
-
最大50桁の実数の和・差・積を...
-
加算と減算で乗算と除算を表現...
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
O(n log n)について2
-
VB.net Double と...
-
c languageで 簡単な質問があ...
-
ExcelのINT関数の計算結果がお...
-
有効数字について 以前質問をし...
-
ExcelでPC(パソコン)によって...
-
三菱シーケンサ(Aシリーズ)で...
-
除算を使わずに10で割りたい。
-
16進数 加算 減算 C言語
-
EXCELの関数"STDEV(標準偏差)"...
-
VB6.0での小数点の扱いについて
-
”/”を使わずに割り算したいんで...
-
距離から緯度経度を求める方法
-
VBAでミリ秒まで出力する方法
-
floatの有効桁数
-
コンピューターは指数関数をど...
-
時刻の比較
-
計算の丸め誤差の解消について
-
Double型について
-
powf を使わずにべき乗を計算
おすすめ情報