人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

Delphiと.NETでは実数の条件比較の内部処理に違いがあるのでしょうか?
とあるシステムの移植で計算した結果をもとに一定の値ごとに分類してグラフを描画する処理があるのですが同じように条件を書いたのに一部の値がDelphiと.NETで結果が異なってしまいます。
例えば
float n = 3.55;
if(n < 3.6){…}
のときに内部処理の仕様の違いによってDelphiだとnが3.6と見なされてfalseになって、.NETだと普通に「3.55<3.6」と比較されてtrueになるということがあるのでしょうか?
過去に似たような事例等がありましたらご教授をお願いします。

●質問者: えんどう
●カテゴリ:コンピュータ
○ 状態 :終了
└ 回答数 : 1/1件

▽最新の回答へ

1 ● a-kuma3
●100ポイント

質問では、

float n = 3.55;
if(n < 3.6){…}

とありますが、n は 3.55 ではなく計算で求められた値だと思います。
(多分)C# で、質問にある通り float なのでしょう。
Delphi の方は、実数の型は REAL でしょうか。

C# の float は IEEE 754 でいうところの Single Format です。
2進数での指数形式で、仮数部の桁数は 2進数で 23bit です。

Delphi の REAL は IEEE 754 でいうところの Double Format です。
こちらも 2進数での指数形式で、仮数部の桁数は 2進数で 52bit あります。

比較している Delphi と C# のプログラムでは、精度が違う実数型で計算しているために桁落ちが発生していて、比較している値(こちらは、定数か?)と近いところでは誤差が生じているのだと思います。
C# の方を、計算過程も含めて全て double で計算すれば同じ結果になると思います。
質問の文面にあるような、3.55 と 3.6 の比較であれば、float でも double でも同じ判定結果になります。


以下、C のプログラムですが float と double で、0.01 を 100回足したときの比較です。

#include <stdio.h>

void test_float() {
 float d = 0.01f;
 float n = 0.0f;
 for (int i = 0 ; i < 100 ; ++i) {
 n += d;
 }
 if (n < 1.0) {
 printf("float: n (%f) < 1.0\n", n);
 } else {
 printf("float: n (%f) >= 1.0\n", n);
 }
}

void test_double() {
 double d = 0.01;
 double n = 0.0;
 for (int i = 0 ; i < 100 ; ++i) {
 n += d;
 }
 if (n < 1.0) {
 printf("double: n (%f) < 1.0\n", n);
 } else {
 printf("double: n (%f) >= 1.0\n", n);
 }
}

int main(void) {
 test_float();
 test_double();
 return 0;
}

試してみると分かりますが、同じ結果にはなりません。
http://ideone.com/HG6j4I



以下、参考 URL。
C#
https://msdn.microsoft.com/en-us/library/b1e65aza.aspx
https://msdn.microsoft.com/en-us/library/678hzkk9.aspx

IEEE 754
https://docs.oracle.com/cd/E19422-01/819-3693/ncg_math.html#pgfId-344
https://docs.oracle.com/cd/E19422-01/819-3693/ncg_math.html#pgfId-610

Delphi
http://docwiki.embarcadero.com/RADStudio/XE8/ja/%E5%8D%98%E7%B4%94%E5%9E%8B#.E5.AE.9F.E6.95.B0.E5.9E.8B

関連質問

●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ