-1

iPhone アプリケーションでフロートの丸めに問題があります。

float f=4.845;
float s= roundf(f * 100.0)/100;
    NSLog(@"Output-1: %.2f",s);
      s= roundf(484.5)/100;
    NSLog(@"Output-2: %.2f",s);

Output-1: 4.84
Output-2: 4.85

これで何が問題なのか、これを解決する方法を教えてください。

4

2 に答える 2

7

問題は、浮動小数点に固有の問題の 1 つ、つまりほとんどの数値を正確に(a)で表すことができないという事実をまだ認識していないことです。

これは4.845、実際には、4.8449999999999それを丸めると、4.84期待したものではなく、 のようなものになる可能性が高いことを意味します4.85

また、最終的にどのような値になるかは、計算方法によっても異なります。そのため、異なる結果が得られます。

そしてもちろん、信頼できる What Every Computer Scientist Should Know About Floating-Point Arithmetic がなければ、浮動小数点の「不正確さ」の答えは SO では完全ではありません。


(a) IEEE754 で正確にレンダリングできるのは、特定の類似した範囲内の 2 の正確な累乗の合計のみです。たとえば484.5

256 + 128 + 64 + 32 + 4 + 0.5( )。28 + 27 + 26 + 25 + 22 + 2-1

IEEE754 形式の詳細については、この回答を参照してください。


それを解決するには、いくつかの選択肢があります。double1 つはの代わりに使用することですfloat。これにより、精度が向上し、数値の範囲が広がりますが、実際に問題を解決するのではなく、問題を遠ざけるだけです。0.1は IEEE754 の繰り返し分数であるため、正確に表すことのできるビット数 (無限を除く) はありません。

もう 1 つの選択肢は、big decimal 型のようなカスタム ライブラリを使用することです。これは、任意の精度の小数を表すことができます (これは、メモリによって制限されるため、何人かの人々が示唆するように、無限の精度ではありません)。これにより、2 進数と 10 進数の不一致によるエラーが減少します。

調べることもできますNSDecimalNumber-これにより任意の精度が得られるわけではありませんが、正確な10進数表現で広い範囲が得られます。

PI や 2 の平方根、その他の無理数など、表現できない数値はまだありますが、ほとんどの場合をカバーするはずです。これらの他の値を本当に処理する必要がある場合は、シンボリック数値表現に切り替える必要があります。

于 2013-03-16T07:51:08.593 に答える
2

float *484.5として正確に表現できるものとは異なり、は次のように表されます (他の数値を試したい場合は、この計算機を参照してください)。100 を掛けると、数値はに保たれ、正確に に丸められます。 4.8454.8449998484.49998484


*小数部分0.5が 2 のべき乗 (つまり2^-1) であるため、正確な表現が可能です。

于 2013-03-16T07:55:04.470 に答える