NSDecimalNumber
NSDecimalNumberとは10進数を表すオブジェクトです。NSNumberを継承しており、四則演算 を行うためのラッパーを提供しています。インスタンス自体は、仮数×10^(指数)として表示可能な数値を表します。それぞれ、仮数は10進数の38桁整数、指数は-128〜127の整数を扱うことができます。
四則演算
加法
" + "の代わりにdecimalNumberByAddingメソッドを使用する。
// result = first + second;
NSDecimalNumber *result = [first decimalNumberByAdding:second];
減法
" - "の代わりにdecimalNumberBySubtractingメソッドを使用する。
// result = first - second;
[first decimalNumberBySubtracting:second];
乗法
" * "の代わりにdecimalNumberByMultiplyingByメソッドを使用する。
// result = first * second;
[first decimalNumberByMultiplyingBy:second];
除法
" / "の代わりにdecimalNumberByDividingByメソッドを使用する。
// result = first / second;
[first decimalNumberByDividingBy:second];
その他の演算
累乗を求める
10進数の値を累乗(2乗や3乗など)した結果を返す。
第1引数はNSUInteger型で指定する。
// dNum^(power) : dNumのpower乗
[dNum decimalNumberByRaisingToPower:power];
(例) 2の10乗を求める場合
- (void)doPowerUp {
NSDecimalNumber *dNum2 = [NSDecimalNumber decimalNumberWithString:@"2"];
NSDecimalNumber *dNum10 = [dNum1 decimalNumberByRaisingToPower:10];
NSLog(@"result = %@",[dNum10 description]); // result = 1024
}
10の累乗を乗算した値を求める
decimalNumberByMultiplyingByPowerOf10メソッドを使用する。
(例) 4の10乗に5.6を乗法した値を求める場合
NSDecimalNumber *dNum4 = [NSDecimalNumber decimalNumberWithString:@"5.6"];
// result = 5.6 * 10^4;
NSDecimalNumber *result = [dNum4 decimalNumberByMultiplyingByPowerOf10:4];
値にアクセスする
レシーバのNSDecimalの数値(読み込みのみ)
NSDecimalNumber *dNum7 = [NSDecimalNumber decimalNumberWithString:@"7"];
NSDecimal *dnum7 = dNum7.decimalValue;
10進数オブジェクトの近似値のdoubleの数値(読み込みのみ)
NSDecimalNumber *dNum10 = [NSDecimalNumber DecimalNumberWithString:@"10"];
double num10 = dNum10.doubleValue;
最大値と最小値
1. maximumDecimalNumber
NSDecimalNumber型が扱うことができる最大値を取得する。
NSDecimalNumber *maximum = NSDecimalNumber.maximumDecimalNumber;
2. minimumDecimalNumber
NSDecimalNumber型が扱うことができる最小値を取得する。
NSDecimalNumber *minimum = NSDecimalNumber.maximumDecimalNumber;
3. notANumber
数ではない十進数オブジェクトを作って返す。
NSNumber *aNA = [NSDecimalNumber notANumber];
(例)
NSDecimalNumber *Num = ....
[[NSDcimalNumber notANumber] isEqualToNumber:Num];
4. "1"を作る
1の値を持つNSDecimalNumberオブジェクトを作成する。
NSDecimalNumber *dNum1 = NSDecimalNumber.one;
5. "0"を作る
0の値を持つNSDecimalNumberオブジェクトを作成する。
NSDecimalNumber *dNum0 = NSDecimalNumber.zero;
NSString列からNSDecimalNumberオブジェクトを作成する
(例)文字列"7"からNSDecimalNumber型を作成する。
NSDecimalNumber *dNum7 = [NSDecimalNumber decimalNumberWithString:@"7"];
NSDecimalNumberオブジェクトからNSString型を作成する
(例)NSDecimalNumber型"7"から文字列を作成する。
NSDecimalNumber *dNum7 = [NSDecimalNumber decimalNumberWithString:@"7"];
NSString *str7 = [NSString stringWithFormat:@"%f",dNum7.doubleValue];
NSDecimalNumber *dNum7 = [NSDecimalNumber decimalNumberWithString:@"7"];
NSString *str7 = dNum7.stringValue;
10進数からNSDecimalNumberオブジェクトを作成する
(例)
NSNumber *num = [NSNumber numberWithFloat:233.333];
NSDecimalNumber *dNum = [NSDecimalNumber decimalNumberWithDecimal:[num decimalValue]];
10進数計算の精度や丸め方を指定する
小数点を含む数値
小数点を含む数値を計算する場合には系統的な誤差が生じます。詳しくはこちらを参考にしてください。
-(NSDecimalNumber *)decimalNumberByRoundingAccordingToBehavior:(id <NSDecimalNumberBehaviors>)behavior:
丸めた十進数オブジェクトを返します。レシーバが3.141592でデフォルトの丸めを使えば3.14を返します。
NSDecimalNumberHandler
浮動小数点がある場合には、小数点を丸める処理が必要になる場合があります。この場合、NSDecimalNumberHandlerクラスを使用します。数値の丸め方decimalNumberHandlerWithRoundingModeメソッドを使用してカスタム設定します。
+ (NSDecimalNumber *)convertScaleWithDecimalNumber:(NSString *)aNumber
scale:(NSInteger)aScale {
if (!aNumber) return [[NSDecimalNumber alloc] initWithString:@"0"];
NSDecimalNumber *decimalValue = [[NSDecimalNumber alloc] initWithString:aNumber];
NSDecimalNumberHandler *roundingStyle
= [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundPlain
scale:aScale
raiseOnExactness:NO
raiseOnOverflow:NO
raiseOnUnderflow:NO
raiseOnDivideByZero:NO];
return [decimalValue decimalNumberByRoundingAccordingToBehavior:roundingStyle];
}
+ (NSDecimalNumber *)getScaleWithDecimalNumber:(NSDecimalNumber *)aNumber
scale:(NSInteger)aScale {
NSDecimalNumberHandler *roundingStyle
= [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundPlain
scale:aScale
raiseOnExactness:NO
raiseOnOverflow:NO
raiseOnUnderflow:NO
raiseOnDivideByZero:NO];
return [aNumber decimalNumberByRoundingAccordingToBehavior:roundingStyle];
}
引数 | 引数名 | |
---|---|---|
第1引数 | roundingMode | NSRoundPlain:四捨五入 NSRoundDown:切り下げNSRoundUp:切り上げ |
第2引数 | scale | 丸めた結果の桁数 |
第3引数 | raiseOnExactness | 精度が狂った場合、エラーを発生させるか |
第4引数 | raiseOnOverflow | オーバーフロー場合、エラーを発生させるか |
第5引数 | raiseOnUnderflow | アンダーフローした場合、エラーを発生させるか |
第6引数 | raiseOnDivideByZero | 0で除算した場合、エラーを発生させるか |
NSDecimalNumberBehaviorsプロトコル
適合するプロトコル
NSDecimalNumberBehaviors
– roundingMode
– scale
– exceptionDuringOperation:error:leftOperand:rightOperand:NSCoding
– encodeWithCoder:
– initWithCoder:
十進数ハンドラの作成
defaultDecimalNumberHandler
デフォルトの十進数ハンドラを作って返しますdecimalNumberHandlerWithRoundingMode: scale: raiseOnExactness
raiseOnOverflow: raiseOnUnderflow: raiseOnDivideByZero
カスタマイズされた十進数オブジェクトの計算の動作を作って返します
十進数ハンドラの初期化
– initWithRoundingMode: scale: raiseOnExactness
raiseOnOverflow:raiseOnUnderflow:raiseOnDivideByZero
カスタマイズされた十進数オブジェクトの計算の動作を初期化して返します
Swiftとの関係
Foundation.frameworkに関して、Swiftは表面上ではNSDecimalNumberクラスとの橋渡しがされており、10進数のしくみを提供しています。10進数の値型は、機能面においてNSDecimalNumber参照型と同じものが提供されているため、Objective-CのAPIと相互作用するようなSwiftコードの場合、両者はどちらでも利用可能です。この振る舞いは、標準的な文字列、数値、あるいはFoundationクラスに対応しているcollection型とのSwiftの橋渡し方法と似ています。
参考
https://developer.apple.com/reference/foundation/nsdecimalnumber?language=objc
http://cocoaapi.hatenablog.com/entry/10010412/NSDecimalNumber
http://hidef.jp/post-449/