質問

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

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

作業中のアプリは国際化されることに注意してください。金額を数えるオプションは実際には実行できません。通貨構造は使用するロケールに大きく依存するためです。

NSここに。たぶん答えはほとんどの人にとって明らかですが、アプリの大規模なリファクタリングを開始する前に確認したいと思います。

説得してください:)

役に立ちましたか?

解決

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

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

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

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

他のヒント

はい。使用する必要があります

NSDecimalNumber および

iOSで通貨を扱う場合、

double float ではありません。

なぜですか?

$ 10

ではなく、 $ 9.9999999998 のようなものを取得したくないためです。

どのように発生しますか??

floatsおよびdoublesは近似値です。それらには常に丸め誤差があります。コンピューターが小数を格納するために使用する形式により、このルーティングエラーが発生します。 詳細が必要な場合は読んでください

http://floating-point-gui.de/

アップルのドキュメントによると、

NSDecimalNumberは、NSNumberの不変のサブクラスであり、10進数の算術演算を行うためのオブジェクト指向のラッパーを提供します。インスタンスは仮数x 10 ^ exponentで表現できる任意の数を表すことができます。仮数は最大38桁の10進整数で、exponentは10を基数とする算術演算の– 128〜127.wrapperの整数です。

したがって、NSDecimalNumberは通貨を扱うために一般化されています。

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

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

唯一の適切な解決策はNSDecimalNumber(またはそれに似たもの)で、問題を10 ^ -128¢に先送りします。 (つまり、
0.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
000000000000000000000000000000000000001¢)。

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

[編集:どうやら、少なくとも1人がブラッドラーソン—この答えのどこかでバイナリ浮動小数点について話していると思います。違います。]

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

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

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

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top