2011-01-13 22 views
2

私が得る8個の浮動小数値の最大値と最小値を求める必要があります。私は次のようにしました。しかし、浮動小数点の比較は、良いCの本によって警告されるようにうまくいっていません! maxとminを正確に計算するにはどうすればよいですか?8個の浮動小数点値の最大値/最小値を計算する方法

main() 
{ 
    float mx,mx1,mx2,mx3,mx4,mn,mn1,mn2,mn3,mn4,tm1,tm2; 

    mx1 = mymax(2.1,2.01); //this returns 2.09999 instead of 2.1 because a is passed as 2.09999. 
    mx2 = mymax(-3.5,7.000001); 
    mx3 = mymax(7,5); 
    mx4 = mymax(7.0000011,0); //this returns incorrectly- 7.000001 
    tm1 = mymax(mx1,mx2); 
    tm2 = mymax(mx3,mx4); 
    mx = mymax(tm1,tm2); 

    mn1 = mymin(2.1,2.01); 
    mn2 = mymin(-3.5,7.000001); 
    mn3 = mymin(7,5); 
    mn4 = mymin(7.0000011,0); 
    tm1 = mymin(mx1,mx2); 
    tm2 = mymin(mx3,mx4); 
    mn = mymin(tm1,tm2); 


    printf("Max is %f, Min is %f \n",mx,mn); 

    getch(); 
} 

float mymax(float a,float b) 
{ 
    if(a >= b) 
    { 
     return a; 
    } 
    else 
    { 
     return b; 
    } 
} 

float mymin(float a,float b) 
{ 
    if(a <= b) 
    { 
     return a; 
    } 
    else 
    { 
     return b; 
    } 
} 

これらの浮動小数点数を正確に比較するにはどうすればよいですか?これはすべてのCコードです。

ありがとうございました。

-AD。

+3

「フロート」データ型の精度は、ここで何をしようとしているのかでは不十分です。 IEEE754の 'float' - http://en.wikipedia.org/wiki/Binary32 - 符号/指数/仮数のための' 1 + 8 + 23'ビットしかなく、丸め誤差はすでに6桁の10進数で非常に見えるようになります。 'double'やGMPのような任意精度の数学ライブラリを使うことができない特別な理由はありますか? –

+2

'float'の代わりに' double'を使うと正確に表現できないという問題は解決しません。 –

+0

正確にはdoubleを使うとこの場合は役に立ちません。 – goldenmean

答えて

2

であり、これらの浮動小数点数を正確に比較しています。問題は(少なくともあなたのコード例で)floatは、リテラルの値を十分に表すのに十分な精度の桁がないということです。 7.0000017.0000011は、単に互いに接近しているため、32ビットの仮数は、それらを別々に表すことができません。

しかし、この例は人工的なようです。あなたが解決しようとしている真の問題は何ですか?あなたは実際にどのような価値を持っていますか?それとも単なる学問的な運動ですか?

最高の解決策はその答えに依存します。実際の値がfloatよりも精度がいくらか必要な場合は、doubleを使用してください。小数点の正確な表現が必要な場合は、小数点型のライブラリを使用します。浮動小数点値がどのように機能するかを理解したければ、The Floating-Point Guideを読んでください。

+0

@Agreedこれは調理された例です。しかし、浮動小数点の実際の値は、2つの浮動小数点の浮動小数点の差の以前の浮動小数点除算の結果です。 – goldenmean

+0

@ goldenmean:だから実際の問題はどこですか?まれにしか起こらない結果が生じることがあります。その結果、浮動小数点値の精度が完全に正確なデータ型と同じ順序で表されないように、密接に結びついています。あなたの入力データは本当に*正確ではありますか? –

+0

@Michael:そうです。助けてくれてありがとう。私は慎重に私の浮動小売店を見ているとき。あるデータポイントが実際には非常に正確であったために浮動小数点数では表現できない場合もありましたが、この比較(最大/最小計算)の前に起こる算術演算は既にその精度を失っており、この最大/最小計算への入力は近似である。だから私はその部分について心配する必要はありません。入力として得られるものの最大値/最小値を与えるだけです。 – goldenmean

0

フロートの正確な比較ができます。浮動小数点として直接、または同じビット表現でintにキャストします。

float a = 1.0f; 
float b = 2.0f; 
int &ia = *(int *)(&a); 
int &ib = *(int *)(&b); 

/* you can compare a and b, or ia and ib, the results will be the same, 
    whatever the values of the floats are. 
    Floats are ordered the correct way when its bits are considered as int 
    and thus can be compared (provided that float and int both are 32 bits). 
*/ 

しかし、あなたは正確に2.1フロートなどを表現することはできませありません。

あなたの問題は比較の問題ではなく、値の表現の問題です。

0

値が変更されていないため、これらの比較は実際に正確であると主張します。

多くの浮動小数点数は、IEEE-754浮動小数点数では正確に表現できないという問題があります。たとえば2.1のように。

基本10桁の数字を正確に表現する必要がある場合は、たとえば、独自の固定小数点BCD算術を書くことができます。同時に、minとmaxを見つけるに関する

少ない比較を必要とする方法は、各インデックスの対のためのものである(2 * I、2 * I + 1)最小値を求める(N/2の比較)

次に、最小値((n-1)/ 2の比較)の最小値と最大値((n-1)/ 2の比較値の最大値)を求めます。

最小と最大の分離を見つけるとき、(2 * n-2)/ 2の代わりに(3 * n-2)/ 2の比較が得られます。

0

<>の比較は、常に浮動小数点数または2倍で正しく動作します。 ==比較にのみ問題があるため、イプシロンを使用することをお勧めします。

min、maxを計算する方法は問題ありません。 floatを使用する場合は、2.1の代わりに2.1fという表記を使用する必要があります。ただのメモ。

+0

数学的に等価な演算が同じ浮動小数点値を生成するのは、それが問題になる==比較自体ではなく、その使用が通常想定しているものです。 –

+0

はい、私の答えは、その意味でいくつかの詳細が欠けています。 – ypnos

関連する問題