私は文字通り、2 つの浮動小数点数の乗算を行っているだけです。これらのステートメントが異なる結果をもたらすのはなぜですか? float を使用する必要がありますか?
500,000.00 * 0.001660 = 830
私は文字通り、2 つの浮動小数点数の乗算を行っているだけです。これらのステートメントが異なる結果をもたらすのはなぜですか? float を使用する必要がありますか?
500,000.00 * 0.001660 = 830
これらのステートメントが異なる結果をもたらすのはなぜですか?
浮動小数点演算は正確ではなく、乗数を十分に正確に出力していないようです (つまり、十分な数の 10 進数)。そして、それは丸みを帯びたものに過ぎませんでし.00166
た。 0.00166
float を使用する必要がありますか?
いいえ。お金については、整数を使用し、固定小数点の有理数として扱います。(これらはまだ正確ではありませんが、大幅に改善され、エラーが発生しにくくなっています。)
をどのように初期化したかを示しておらずperiodicInterest
、おそらく に設定したと思われます0.00166
が、実際には出力のエラーが十分に大きいため、明示的に として初期化してはいけませんperiodicInterest = 0.00166
。に近づく必要があり0.00165975
、 と の差は、単一の浮動小数点の丸め誤差にならないほど大きいことは間違いありません0.00166
。0.00165975
金額を扱う場合は、NSDecimalNumber
または を使用する必要がありますNSDecimal
。
を使用することの明らかでない利点の 1 つNSDecimalNumber
は、 で動作するNSNumberFormatter
ことです。そのため、あらゆる種類の外国ロケールの通貨の書式設定を Apple に任せることができます。
コメントへの応答:
「<code>periodicInterest は明らかに金銭的な量ではありません」と「12 で割った場合、10 進数は 2 進数よりも誤差がないわけではありません」 - 不正確な量については、次の 2 つの懸念事項が考えられます。
懸念事項の 1 つは、正確な結果を得るために十分な精度を使用することです。 NSDecimalNumber
精度が 38 桁で、指数が -128 ~ 127 の範囲の浮動小数点数です。これは、IEEE の「double」が格納できる 10 進数の 2 倍以上です。指数の範囲は a の範囲よりも小さいですがdouble
、金融計算では問題にならない可能性があります。そのため、s はs やsNSDecimalNumber
よりも確実に誤差が小さくなりますが、1/12 を正確に格納できるものはありません。float
double
もう 1 つの懸念は、銀行、ブローカー、NYSE などの他のシステムによって計算された結果と一致することです。その場合、他のシステムがどのように数値を格納し、計算しているのかを把握する必要があります。他のシステムが 10 進形式を使用している場合 (金融部門でよく使用されます)、NSDecimalNumber
おそらく役立つでしょう。
「プリミティブ型を使用して浮動小数点演算、特に数千をリアルタイムで行う方が効率的ではないでしょうか。」プリミティブ型の算術演算は、s の算術演算よりもはるかに高速ですNSDecimalNumber
。測定したことはありませんが、100 倍であっても驚かないでしょう。
要件間のバランスを取る必要があります。小数の精度が最重要である場合 (金融プログラミングではよくあることです)、精度のためにパフォーマンスを犠牲にする必要があります。小数の精度がそれほど重要でない場合は、プリミティブ型の使用を慎重に検討できますが、犠牲にしている精度に注意する必要があります。それでも、a のサイズfloat
は非常に小さい (通常は 10 進数の有効桁数が 7 桁のみ) ため、おそらく使用する必要がありますdouble
(少なくとも 15 桁、通常は 16 桁の有効桁数)。
真の 10 進精度で 1 秒あたり数百万回の算術演算を実行する必要がある場合は、 double
sを使用して実行できる可能性があります。コードを分析して、エラーが発生した場所とその除去方法を特定できるIEEE 754 の専門家であれば可能です。 . このレベルの専門知識を持っている人はほとんどいません。また、コンパイラがどのように Objective-C コードを機械語命令に変換するかを理解する必要があります。
とにかく、おそらく、正味現在価値または将来価値の大まかな見積もりを計算するためのカジュアルなアプリを作成しているだけかもしれません。その場合、おそらく using でdouble
十分でしょうが、 usingNSDecimalNumber
もおそらく十分に高速です。あなたが作成しているアプリについて詳しく知らなければ、これ以上具体的なアドバイスをすることはできません。