2009-11-09 19 views
26

私はNSDecimal、のNSNumber、NSNumberDecimal、CFNumberについて多くを読んで...、それは私にはジャングルのようなものであることを開始します。NSDecimal、NSDecimalNumber、CFNumber間の正しい選択とは何ですか?

基本的に、私はこの1つのように、簡単な計算を処理する単純なモデルクラスを作成しようとしています:

#import <Foundation/Foundation.h> 


@interface Test : NSObject 
{ 
    float rate; 
    float amount; 
    int duration; 
} 

- (float)capitalizedAmount; 

@end 

@implementation Test 

- (float)capitalizedAmount { 
    return (amount*pow((1.0+rate),duration)); 
} 

@end 

私が計画しているので、私は、文字列としてその名前を持つこれらのメソッドとセッターにアクセスしたいですこのようなクラスがたくさんあるので、キー値のコーディングを行うフィールドのリストのみを保持しています。

// This is just the desired behavior 
// This evidently won't work with the previous class definition 
Test *obj = [[Test alloc] init]; 
[NSNumber numberWithInt:10] 
... 
float r; 
r = [obj performSelector:NSSelectorFromString(@"capitalizedAmount")]; 

私はperformSelector:capitalizedAmountがオブジェクトを返す必要があることをこのようにオブジェクトを返す、となると、これが不可能であることを理解しています。私はNSInvocationとcomp.langのObjective-C Faqに関連する部分について読みました。

はまた、私はNSDecimalNumberを使用する必要があることを理解し、私は知りたいのですが二つのものがあります:

  1. はやや複雑クラス(の唯一の金融計算のための許容可能なオーバーヘッドメモリとパフォーマンスの損失ですこの種は、UITableViewで示された)?私は
  2. は、それはあまりにも潔癖と複雑decimalNumberByAdding:のような機能を使用しないようにしたのは... Cに多くのバックグラウンドを持っていませんか? Pythonでは、オブジェクトを持つ演算子を使用するために__add__を定義するのは簡単でした。私はその後の計算を行い、NSDecimalNumberから値を取得し、フロートNSDecimalNumberに包まれた結果を返すべきでしょうか?どのようにこの問題に対処しますか?

私はシンプルで美しい解決策を探しています!

同じエリアの別の質問:CFBoolean iPhone Core FoundationのBOOLのオブジェクトラッパーですか?

ありがとうございました!

答えて

24

財務計算を扱う場合は、実際にはベース10の算術を使用して、標準の2の浮動小数点型で発生する丸め誤差を避ける必要があります。つまり、NSDecimalまたはNSDecimalNumberです。また、オブジェクト指向のコードを記述しているので、NSDecimalNumberが最適です。

質問に答えるには:コードのテストだけで、メモリのオーバーヘッドとパフォーマンスの低下があなたに受け入れられるかどうかがわかります。私はNSDecimalNumberで実際にはあまり働いていませんが、私はAppleの実装がかなり効率的で、ほとんどの人のニーズには十分以上になると賭けています。

残念ながら、Objective-CはC++のように演算子のオーバーロードをサポートしていないので、decimalNumberByAdding:のようなものは避けられません。私はあなたのコードがややエレガントでないことに同意します。あなたが投稿したコードに

ワンコメント:r = [obj performSelector:NSSelectorFromString(@"capitalizedAmount")];はかなりunelegantです。

r = [obj performSelector:@selector(capitalizedAmount)]; 

、あるいはどちらかあなたが何らかの理由でNSSelectorFromString構文を必要としない限り、単純な

r = [obj capitalizedAmount]; 

が良いだろう。

+0

ありがとう、私は実際に文字列からセレクタを作成する必要があります。 CFBooleanはBOOLを折り返すための正しいオブジェクトですか? – charlax

+1

Cocoaでは、NSNumberを使用してオブジェクト内のBOOLをラップする必要があります。 '+ [NSNumber numberWithBool:]'を参照してください。 –

2

私はこのような他の多くのクラスを予定しているので、これらのメソッドとセッターの名前を文字列としてアクセスしたいと思います。キー値コーディングを行うフィールドのリストのみを保持しています。

r = [obj performSelector:NSSelectorFromString(@"capitalizedAmount")]; 

KVCは、単純に文字列を使用してオブジェクトにメッセージを送信していません。 the Key-Value Coding Programming Guideを参照してください。

NSDecimalNumberから浮動小数点値を取得する必要がありますか?計算を行い、NSDecimalNumberにラップされた結果を返しますか? 10進浮動小数点から(float/double)(NSDecimal/NSDecimalNumber)を浮動小数点をバイナリに

番号変換は非可逆です。あなたがそうしたやり方をすれば、あなたの結果は正しく計算されません。

19

財務計算の際に浮動小数点数学のエラーを避けるには、NSDecimalまたはNSDecimalNumberを使用してください。しかし、私の提案は、NSDecimalNumberではなくNSDecimalとそのC関数を使うことです。 NSDecimalの計算ははるかに高速になる可能性があります。また、オートレリースされたオブジェクトの作成を避けるため、メモリ使用量がはるかに向上します。一例として、

、私は私のMacBook Airの上の2つのタイプのための数学演算ベンチマーク:

NSDecimal 

Additions per second: 3355476.75 
Subtractions per second: 3866671.27 
Multiplications per second: 3458770.51 
Divisions per second: 276242.32 

NSDecimalNumber 

Additions per second: 676901.32 
Subtractions per second: 671474.6 
Multiplications per second: 720310.63 
Divisions per second: 190249.33 

部門はNSDecimalNumber対NSDecimalを使用する場合のパフォーマンスでおよそ五倍の増加を経験しなかっただけで、操作しました。同様のパフォーマンスの改善がiPhoneで発生します。これはメモリの節約と同時に、最近Core PlotをNSDecimalを使用するように切り替えた理由でした。

唯一の問題は、NSDecimal型に値を渡すことです。浮動小数点数と整数値を直接やりとりするには、NSDecimalNumberをブリッジとして使用する必要があります。また、コアデータを使用する場合は、値をNSDecimalではなくNSDecimalNumbersとして保存します。

+0

私はすでに見てきた非常に興味深いベンチマークのためにBradに感謝します。私はNSDecimalNumberを使いやすくするためにNSDecimalNumberの使用を計画しています。近い将来、Core Dataを使用します。ところで、私はあなたのグラフィカルライブラリほどのスピードは必要ありません! – charlax

+0

floatまたはdoubleからNSDecimalを作成する最も簡単な方法は何ですか? – Paul

+0

@Paul - さまざまな変換を行ういくつかのヘルパー関数については、Core PlotフレームワークのCPUtilities.mファイルをご覧ください:http://code.google.com/p/core-plot/source/browse/framework/Source/CPUtilities.m 。個人的には、フォーマット・ストリングを使用してNSDecimalNumberインスタンスを作成し、そこから 'decimalValue'を取得しました。これは、コア・プロット・ルーチンで行われるNSNumberからNSNumberからNSDecimalへの変換について少しパラノイです。 –

関連する問題