
ある問題を数値的に解こうと思いFortranでプログラムを組んでいるのですが、倍精度の数値計算で以下のような事が起きて困っています。
プログラムの中で
A=B-C*D (変数は全て倍精度実数変数)
のような代入文があるのですが、
write(*,*) B,C,D
とすると、0.250000000000000 0.500000000000000 0.500000000000000
と表示されるのですが、
write(*,*) B-C*D や write(*,*)A
では-1.79570984817912D-017 などと表示されます。(この数値に意味はないのでしょうが、同じシチュエーションでは常に同じ値が表示されます)
入力した値の精度外の「誤差」ですが、どこに原因のある問題でしょうか?
因に使っているコンパイラはintelのサイトで入手したフリーの評価版ifc ver.6 でそれにpentium4に最適化するオプションをつけてコンパイルしています
No.3ベストアンサー
- 回答日時:
他に間違っている部分がなくて、その通りとするとおかしいですね。
本当にB,C,Dに0.2,0.5の数字が入っていてそうなるのであればコンパイラのバグかもしれませんが、オーダーが大きすぎるし、pen4が実際には計算している筈なので余り考えられません。
一応、最適化オプションをはずして試しても同じですか?
あと、単精度ではどうですか?
0.25, 0.5 という数字は2進数では割り切れる数値なのでそのようなことが起きること自体が不思議です。
気になるのは一見0.25とか0.5に見えても、何らかの計算の結果の数値とすればそのような現象になるのは至極当然のことです。
というのも、表示するときには必ず丸められて表示されるので、0.2とか0.5に対してD-17だと完全に丸められる領域だからです。
差分をとったときにはもちろんクローズアップするのでわかります。
試しに、 0.5 - 0.5 が 0になることを確認して、 C - 0.5 を表示させるなどすれば、Dが本当に0.5なのかどうかがわかります。
もう一つは、一度単精度の変数に代入して、また倍精度の変数にいれるとか、あるいは関数を使って下10桁で四捨五入処理するなどですね。
この手の話は良くあることです。
ありがとうございました。
>試しに、 0.5 - 0.5 が 0になることを確認して、 C-0.5
>を表示させるなどすれば、Dが本当に0.5なのかどうかがわかります。
教えていただいたことを実行してみたところ、0.25に関してゴミがそのままでてきました。
なるほどこういうことがあるんですね。勉強になりました。
>この手の話は良くあることです。
のようですね。うっかり周りにいた詳しい人にも尋ねた所、大笑いされてしまいました。
どうもお世話になりました。

No.4
- 回答日時:
一つの可能性は.
B=0.25
のように指定すると.Bは倍精度.0.25は単精度と解釈して.0.250000(中略)123...なんて数値が代入されている可能性があります。
0.25d1
のような倍精度を指定して代入式を作ってみてください。
これが失敗した場合には.全部整数で代入式を作り演算によって倍精度にする方法があります。
インテルの場合.たしか.有効桁以下は0以外の数値が入っている場合が多いので.これが変な数値の原因となっていると考えられます。
ありがとうございます
>0.25d1
>のような倍精度を指定して代入式を作ってみてください。
ご指摘の通り代入式もいい加減でした。レベルがばれそうで恥ずかしいです。全部書き直しました。直接の原因ではなかったみたいですがこれから気をつけることにします。
>インテルの場合.たしか.有効桁以下は0以外の数値が入っている場合が多いので.これが変な数値の原因となっていると考えられます。
確かにそうでした。これからは気をつけたいです。
みなさんありがとうございました。この場をかりてお礼申し上げます。
No.2
- 回答日時:
同じくFortranはよく知らないのですが…。
お使いになっているFortranではBCD (Binary Coded Decimal, 二進化十進数→参考URL) 型の実数は扱えないのでしょうか?
これが使えれば,誤差の問題は解決出来るかもしれません。
参考URL:http://www.ffortune.net/comp/develop/data/kazu.htm
ありがとうございました。
はずかしいことに二進化十進数は初耳でした。でも確かにこうしないとだめですよね。私のもっているfortranの教科書には実数は単精度、倍精度などの分類はありますが内部での表現の指定方法はないです。無いのかもしれないです。
他のfortranのコンパイラでは問題の無いプログラムなんですが。
No.1
- 回答日時:
Fortranは分からないので恐らくなのですが・・・。
コンピュータで計算を行う場合、大体に置いて2進数で計算を行います。
ところが、小数点を含む計算を行う場合に問題が出てくるのです。
というのは、10進数での特定の数字が2進数では表せないのです。
(詳しい事は昔教えてもらったのですが忘れてしまいました。)
そのため、2進数に変換が出来ないので2進数の近似値で計算を行います。
これによって誤差が生じてくるのです。
一般的に通貨型とか言われているような型でしたら誤差が出ないと思います。
たとえばVisualBasicではCurrency型がそれにあたります。
御返事ありがとうございました。
なにも考えないで計算させてましたが中の事も考えないとだめですよね。
いろいろ考えてみましたが、2進数で循環小数になる場合などは確かに有限桁で切ると誤差の原因になりそうです。
あと、質問には書き忘れましたが、write(*,*)0.25-0.5*0.5は正確に0となります。変数に値が入っている時だけなのです。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- C言語・C++・C# このプログラミング誰か教えてくれませんか 1 2022/06/02 15:27
- C言語・C++・C# このプログラミングの問題を教えてほしいです。 キーボードからデータ数nとn個のデータを入力し、平均値 3 2022/12/19 22:51
- C言語・C++・C# 3つの倍精度浮動小数点値の平均を求めて、3つの引数全てを平均値に変更するメソッドを作成し、キーボード 1 2022/07/13 16:04
- その他(ソフトウェア) F-BASICで計算中の実行が中途で勝手に止まり、大変困っています。 2 2023/03/02 16:15
- C言語・C++・C# このプログラミングの問題を教えて欲しいです。 キーボードから整数kを入力し、kが配列aの中に何個存在 2 2022/12/19 22:50
- Ruby プログラミング 3 2023/06/09 14:30
- 統計学 統計検定2級の過去問について 1 2023/01/04 16:40
- Excel(エクセル) エクセルのセルの書式設定・ユーザー定義の条件設定について 1 2022/08/17 21:56
- Java java 入力された文字列を数値に置き換えて整数にし、計算をしたいです。 <を10として /を1とし 4 2022/05/16 21:08
- C言語・C++・C# [C言語] コメント文字列を無視して、数値データを読み込むプログラム部分について 5 2022/10/05 11:03
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
ExcelでPC(パソコン)によって...
-
O(n log n)について2
-
有効数字について 以前質問をし...
-
c languageで 簡単な質問があ...
-
ExcelのINT関数の計算結果がお...
-
EXCELの関数"STDEV(標準偏差)"...
-
三菱シーケンサ(Aシリーズ)で...
-
VB.net Double と...
-
計算の丸め誤差の解消について
-
除算を使わずに10で割りたい。
-
2進数の足し算(C言語)
-
16進数 加算 減算 C言語
-
”/”を使わずに割り算したいんで...
-
CRCの計算方法について
-
VB6.0での小数点の扱いについて
-
VBAでミリ秒まで出力する方法
-
時刻の比較
-
2進数データのビット演算
-
教えて小数点の比較!(C言語)
-
C言語 型変換のタイミング
おすすめ情報