How to use NSDecimalNumber?

前端 未结 4 551
爱一瞬间的悲伤
爱一瞬间的悲伤 2020-11-30 00:51

I\'m building a app that needs to perform calculations on money.

I wonder how to properly use NSDecimalNumber, especially how to initialize it from integers, floats

相关标签:
4条回答
  • 2020-11-30 00:54

    Design-wise, you should try to avoid converting NSDecimalNumber or NSDecimals to and from int, float, and double values for the same reasons it's recommended you use NSDecimalNumbers: loss of precision and binary floating point representation issues. I know, sometimes it's unavoidable (taking input from a slider, doing trigonometric calculations, etc.), but you should try to take input from users as NSStrings and then use initWithString:locale: or decimalNumberWithString:locale: to generate the NSDecimalNumbers. Do all your math with the NSDecimalNumbers and return their representation to users or save them to SQLite (or wherever) as their string description using descriptionWithLocale:.

    If you have to input from an int, float, or double, you could do something like the following:

    int myInt = 3;
    NSDecimalNumber *newDecimal = [NSDecimalNumber decimalNumberWithString:[NSString stringWithFormat:@"%d", myInt]];
    

    or you could follow Ashley's suggestion to make sure you're safe in the decimal construction.

    0 讨论(0)
  • 2020-11-30 00:56

    The correct way is actually to do this:

    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]);
    

    See more info here.

    0 讨论(0)
  • 2020-11-30 01:01

    Do NOT use NSNumber's +numberWith... methods to create NSDecimalNumber objects. They are declared to return NSNumber objects and are not guaranteed to function as NSDecimalNumber instances.

    This is explained in this thread by Bill Bumgarner, a developer at Apple. I would encourage you to file a bug against this behavior, referencing bug rdar://6487304.

    As an alternative these are all of the appropriate methods to use to create an 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;
    

    If you simply want an NSDecimalNumber from a float or int constant try something like this:

    NSDecimalNumber *dn = [NSDecimalNumber decimalNumberWithDecimal:
                                 [[NSNumber numberWithFloat:2.75f] decimalValue];
    
    0 讨论(0)
  • 2020-11-30 01:03

    One small addition: if you init NSDecimalNumber from a string, it might be useful to set a locale also. For example, if your string contains comma as a decimal separator.

    self.order.amount = [NSDecimalNumber decimalNumberWithString:self.amountText locale:[NSLocale currentLocale]];
    
    0 讨论(0)
提交回复
热议问题