55

最初のアプリのコーディングを開始したとき、よく考えずにお金の値に NSNumber を使用しました。それから、自分の価値観を扱うにはc型で十分かもしれないと思いました。それでも、iPhone SDK フォーラムで、丸め機能が優れている NSDecimalNumber を使用するように勧められました。

気質によって数学者ではないので、仮数/指数のパラダイムはやり過ぎかもしれないと思いました。それでも、ググってみると、ココアのお金/通貨に関するほとんどの話は NSDecimalNumber に言及されていることに気付きました。

私が取り組んでいるアプリは国際化されることに注意してください。そのため、金額をセントで数えるオプションは実際には実行可能ではありません。通貨構造は使用するロケールに大きく依存するからです。

私は NSDecimalNumber を使用する必要があることを 90% 確信していますが、ウェブ上で明確な答えが見つからなかったので (「お金を扱うなら、NSDecimalNumber を使用してください!」のようなもの)、ここで質問したいと思いました。答えはほとんどの人にとって明白かもしれませんが、アプリの大規模なリファクタリングを開始する前に確認したいと思います。

信じさせて :)

4

6 に答える 6

66

Marcus Zarraは、これについてかなり明確なスタンスを持っています。「通貨を扱っている場合は、NSDecimalNumberを使用する必要があります。」 彼の記事は私にNSDecimalNumberを調べるように促し、私はそれに非常に感銘を受けました。基数10の数学を処理するときのIEEE浮動小数点エラーは、しばらくの間私を苛立たせていました(1 *(0.5 --0.4 --0.1)= -0.00000000000000002776)、NSDecimalNumberはそれらを取り除きます。

NSDecimalNumberは、2進数の浮動小数点精度をさらに数桁追加するだけでなく、実際には基数10の計算を行います。これにより、上記の例に示されているようなエラーが取り除かれます。

今、私は記号数学アプリケーションを書いているので、30桁以上の精度と、奇妙な浮動小数点エラーがないことを望んでいることも例外かもしれませんが、一見の価値があると思います。操作は、単純なvar = 1 + 2スタイルの数学よりも少し厄介ですが、それでも管理可能です。数学演算中にあらゆる種類のインスタンスを割り当てることを心配している場合、NSDecimalはNSDecimalNumberと同等のC構造体であり、まったく同じ数学演算を実行するためのC関数があります。私の経験では、これらは最も要求の厳しいアプリケーション(MacBook Airでは3,344,593追加/秒、254,017分割/秒、iPhoneでは281,555追加/秒、12,027分割/秒)を除いてすべて高速です。

追加のボーナスとして、NSDecimalNumberのdescriptionWithLocale:メソッドは、正しい小数点記号を含む、数値のローカライズされたバージョンを含む文字列を提供します。initWithString:locale:メソッドについても同じことが逆になります。

于 2009-01-07T22:46:12.287 に答える
5

(他の回答に対する私のコメントから適応。)

はい、そうすべきです。ペニーの整数は、たとえば 0.5 セントを表す必要がない場合にのみ機能します。その場合は、0.5 セントをカウントするように変更できますが、4 分の 1 セントまたは 8 分の 1 セントを表す必要がある場合はどうでしょうか。

The only proper solution is NSDecimalNumber (or something like it), which puts off the problem to 10^-128¢ (ie,
0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000001¢).

(別の方法は任意精度の算術演算ですが、それにはGNU MP Bignum ライブラリなどの別のライブラリが必要です。GMP は LGPL の下にあります。私はそのライブラリを使用したことがなく、それがどのように機能するのか正確にはわかりません。それがあなたにとってどれほどうまくいくかは言えません。)

[編集: どうやら、少なくとも 1 人の人物 (Brad Larson) は、この回答のどこかで私がバイナリ浮動小数点について話していると考えています。私は違います。]

于 2009-01-07T22:26:13.203 に答える
4

より良い質問は、いつNSDecimalNumberを使用してお金を処理するべきではないかということです。その質問に対する簡単な答えは、NSDecimalNumberのパフォーマンスのオーバーヘッドを許容できず、数桁を超える精度を処理することがないため、小さな丸め誤差を気にしない場合です。さらに短い答えは、お金を扱うときは常にNSDecimalNumberを使用する必要があるということです。

于 2009-01-09T19:50:11.027 に答える
4

整数を使用してセント数を表し、表示のために 100 で割ると便利であることがわかりました。問題全体を回避します。

于 2009-01-07T18:37:02.790 に答える
2

VISA、MasterCards などは、金額を渡す際に整数値を使用しています。通貨の指数に従って金額を正しく解析するのは、送信者と受信者次第です (10^num で割るか乗算します。ここで、num - は通貨の指数です)。異なる通貨には異なる指数があることに注意してください。通常は 2 ですが (したがって、割って 100 を掛けます)、一部の通貨では指数 = 0 (VND など) または = 3 になります。

于 2015-04-08T03:23:39.647 に答える