3

float を小数点以下 1 桁まで表示しようとしています。次のように予期しない結果が得られます。

コード:

float a = 1.25;
float b = 1.35;

NSLog(@"1.25 -> %.1f\n1.35 -> %.1f",a,b);

出力:

1.25 -> 1.2

1.35 -> 1.4

期待される出力、次のいずれか:

1.25 -> 1.3

1.35 -> 1.4

また:

1.25 -> 1.2

1.35 -> 1.3

これは単に 2 進数と 10 進数の間の内部変換によるものですか? もしそうなら、どうすれば期待される動作を得ることができますか?

Xcode 4.6 を使用しています。

編集: わかりました。TonyK と H2CO3 のおかげで、10 進数のバイナリ表現によるものです。

float a = 1.25;
float b = 1.35;
NSLog(@"1.25 -> %.30f\n1.35 -> %.30f",a,b);

1.25 -> 1.25000000000000000000000000000

1.35 -> 1.350000000000000088817841970013

良い情報はたくさんありますが、私が見る限り、2 番目の質問である「期待される動作を得るにはどうすればよいですか?」に取り組んだ人は誰もいません。

Objective-C での数値の丸めは、まったく別の問題です。

4

2 に答える 2

5

1.35 は 27/20 で、2 進数では

1.01 0110 0110 0110 0110 0110 0110....

Afloatは、ほとんどのシステムで 23 ビットの仮数を持っているため (先行する暗黙の 1 は数えません)、これは次のように切り上げられます。

1.01 0110 0110 0110 0110 0110 1

(0110 は明らかに 1000 の半分よりも大きいため)。したがって、それが表示されるまでには、厳密に 1.35 よりも大きくなっprintfています。したがって、1.4。

1.25に関しては、これは次のようにバイナリで正確に表現できます

1.01

したがってprintf、その正確な値が表示されます。しかし、どのように 1.25 を丸めるべきでしょうか? 学校では、5 を 10 に丸めるように教えられました。しかし、最新のシステムのほとんどは、累積的な丸め誤差の影響を軽減するため、ハードウェア レベルで「偶数に丸める」と呼ばれるデフォルトの丸めモードを使用します。これは、数値が丸めの最も近い 2 つの候補の間にある場合、偶数の候補に丸められることを意味します。

したがってprint、10 進出力に「偶数への丸め」を使用しているようです。このイデオン リンクでこの仮説を確認したところ、実際に 1.75 は 1.8 に切り上げられます。これは私にとって驚きですが、大したことではありません。

于 2013-03-31T10:29:44.377 に答える
2

これは、浮動小数点数が正確ではないためです。小数点以下 1 桁に丸め%.1fられた数値を出力しますが、1.2500000 として正確に表すことはできないようです。代わりに、わずかに小さい数値を表すことができます。1.35

この動作については、「すべてのコンピューター科学者が浮動小数点数について知っておくべきこと」を参照してください。

于 2013-03-31T10:00:57.433 に答える