我正在构建一个需要对钱进行计算的应用程序.
我想知道如何正确使用NSDecimalNumber,尤其是如何从整数,浮点数和双精度初始化它?
我发现只使用这种-decimalNumberWithString:
方法很容易.-initWith...
不鼓励使用这些方法,只留下带有尾数的方法,但从来没有使用我之前使用过的7种语言中的任何一种语言,所以我不知道是什么放在那里......
千万不要使用NSNumber
的+numberWith...
方法来创建NSDecimalNumber
对象.它们被声明为返回NSNumber
对象,并不保证作为NSDecimalNumber
实例运行.
这是在这个解释线程比尔布姆加纳,在苹果开发者.我鼓励你提出一个针对这种行为的bug,引用bug rdar:// 6487304.
作为替代方案,这些是用于创建的所有适当方法NSDecimalNumber
:
+ (NSDecimalNumber *)decimalNumberWithMantissa:(unsigned long long)mantissa exponent:(short)exponent isNegative:(BOOL)flag; + (NSDecimalNumber *)decimalNumberWithDecimal:(NSDecimal)dcm; + (NSDecimalNumber *)decimalNumberWithString:(NSString *)numberValue; + (NSDecimalNumber *)decimalNumberWithString:(NSString *)numberValue locale:(id)locale; + (NSDecimalNumber *)zero; + (NSDecimalNumber *)one; + (NSDecimalNumber *)minimumDecimalNumber; + (NSDecimalNumber *)maximumDecimalNumber; + (NSDecimalNumber *)notANumber;
如果你只是想NSDecimalNumber
从一个float
或int
不断尝试这样的事情:
NSDecimalNumber *dn = [NSDecimalNumber decimalNumberWithDecimal: [[NSNumber numberWithFloat:2.75f] decimalValue];
正确的方法实际上是这样做的:
NSDecimalNumber *floatDecimal = [[[NSDecimalNumber alloc] initWithFloat:42.13f] autorelease]; NSDecimalNumber *doubleDecimal = [[[NSDecimalNumber alloc] initWithDouble:53.1234] autorelease]; NSDecimalNumber *intDecimal = [[[NSDecimalNumber alloc] initWithInt:53] autorelease]; NSLog(@"floatDecimal floatValue=%6.3f", [floatDecimal floatValue]); NSLog(@"doubleDecimal doubleValue=%6.3f", [doubleDecimal doubleValue]); NSLog(@"intDecimal intValue=%d", [intDecimal intValue]);
在这里查看更多信息.
在设计方面,您应该尽量避免将NSDecimalNumber或NSDecimals转换为int,float和double值,原因与推荐使用NSDecimalNumbers的原因相同:精度损失和二进制浮点表示问题.我知道,有时它是不可避免的(从滑块输入,进行三角计算等),但你应该尝试从用户那里获取输入作为NSStrings然后使用initWithString:locale:或decimalNumberWithString:locale:来生成NSDecimalNumbers.使用NSDecimalNumbers完成所有数学运算并将其表示返回给用户,或使用descriptionWithLocale:将它们保存为SQLite(或任何地方)作为其字符串描述.
如果必须从int,float或double输入,则可以执行以下操作:
int myInt = 3; NSDecimalNumber *newDecimal = [NSDecimalNumber decimalNumberWithString:[NSString stringWithFormat:@"%d", myInt]];
或者你可以按照Ashley的建议来确保你在十进制结构中是安全的.