2

を引数として受け取り、floatこの float が配列内にあるかどうかを確認するメソッドがあります。これを行うには、最初に float を に変換しNSNumberます。これは私のコードのテスト可能な簡略化です:

float aFloat = 0.3;
NSNumber *aNSNumber = @(aFloat);

NSArray *anArray = @[@(0.0), @(0.3), @(1.0)];
NSLog(@"%d", [anArray containsObject:aNSNumber]);

このコードは0(つまり) ログに記録されるため、 に含まれていないNOと言っています。が、、またはなどの「ラウンド」数である場合、テストは機能し、ログに記録されます(つまり)。上記のように、それ以外の番号は失敗します。0.3anArrayaFloat0.00.51.01YES0.3

一方、 に変更aFloatすると、double機能します。または、次のように変更anArrayすると:

NSArray *array = @[[NSNumber numberWithFloat:0.0], [NSNumber numberWithFloat:0.3], [NSNumber numberWithFloat:1.0]];

それも機能します。私が推測したのは、NSNumber@()表記がnumberWithDouble:.

しかし、私の質問は、 が の場合でも機能するべきではないということaFloatですfloat。とにかく保存して「変換」しているので...そして、とが実際には同じ数字aNSNumberであることを自動的に認識すべきではありませんか?また、なぜ「丸め」の数字が機能するのですか?float 0.3double 0.3

4

3 に答える 3

1

このスニペットを使用して、0.3 と 0.3f の違いを視覚化できます。

NSLog(@"%.20f %.20f", 0.3, 0.3f);

私のデバッガーの表示: 0.29999999999999998890 0.30000001192092895508

面白いことに、「0.3」は「0.3f」よりも正確に見えます。とにかく、0.3f 仕様がすぐに float であるのに対し、コンパイラは float に変換する前に最初にストレート 0.3 を double として受け取る可能性があると推測します。

観察するもう1つのことは、これを行ったかどうかです。

NSArray *anArray = @[@(0.0), aNSNumber, @(1.0)];

containsObject 呼び出しは成功します。おそらく、float を aFloat 宣言とリテラルの間で内部的に使用するものに変換するコンパイラのルートには、いくつかの違いがあります。ここで推測するだけで...

一般に、float や double との等価性をテストするのは好きではありません。精度の問題は、あまりにも簡単に for ループを通過する可能性があります。

于 2013-08-25T14:53:40.517 に答える
1

@(0.3)anArraydouble包まれていNSNumberます。もちろん、あなたaFloatは でfloatラップされていNSNumberます。

次の 2 つの変更のいずれかを試してください。

1)float aFloatに変更double aFloat

また

2) を に変更@(0.3)anArrayます@(0.3f)

于 2013-08-25T06:03:43.153 に答える