views:

80

answers:

3

Man the simplest stuff always seems so crazy in Objective-C to me, anyways I need to do some basic subtraction and multiplication and am stumped.

I have:

client.PricingDiscount <-- this is an Integer 16 property on a CoreData NSManagedObject
sku.RetailPrice <-- this is a Decimal property on a CoreData NSManagedObject

I am simply trying to get a NSDecimalNumber to display like so:

NSDecimalNumber *showPrice = sku.RetailPrice * (100 - client.PricingDiscount);

I have tried a bunch of different forms of this and cannot figure out what the hell I am doing wrong here.

+3  A: 

NSDecimalNumber is an object wrapper for a number--you are treating it like a C value. Instead, try:

float price = [sku.retailPrice floatValue] * (100 - [client.pricingDiscount floatValue]);
NSDecimalNumber *showPrice = [NSDecimalNumber numberWithFloat:price];

It's confusing, but NSNumber and NSDecimalNumber are Objective-C wrappers for C types, typically used for storage in container objects such as NSArray (or Core Data). NSInteger and NSDecimal, on the other hand, are C types (NSInteger just maps to int).

EDIT: falconcreek's answer is better for avoiding accuracy loss. When working with integers, though, you'll typically use unboxed C types.

eman
Risking loss of precision converting retailPrice to a float. Stick with `NSDecimalNumber`
falconcreek
falconcreek's right, the whole reason you'd want to use an NSDecimalNumber for currency is to avoid floating point errors in your calculations. See his answer for a more precise way of doing this.
Brad Larson
Yep, unfortunately there's no autoboxing in Objective-C. One of the things I miss most from other languages.
jshier
A: 
NSDecimalNumber *showPrice = sku.RetailPrice * (100 - client.PricingDiscount);

NSDecimalNumber is a class. What you are doing here is calculating a value, and then assigning that to be the value of a pointer to an NSDecimalNumber object. This is bad mojo.

I haven't used NSDecimalNumber before, but if you need that particular object, what you want is something like this:

NSNumber* number = [NSNumber numberWithFloat:(sku.RetailPrice * (100 - client.PricingDiscount))];
NSDecimal* decimal = [number decimalValue];
NSDecimalNumber* showPrice = [NSDecimalNumber decimalNumberWithDecimal:decimal];
Shaggy Frog
(sku.RetailPrice * (100 - client.PricingDiscount) --> RetailPrice is an instance of NSDecimalNumber this will not work
falconcreek
+3  A: 

Standard operators cannot be used with NSDecimalNumber

NSDecimalNumber *one = [NSDecimalNumber decimalNumberWithDecimal:[[NSNumber numberWithInt:100] decimalValue]]; 
NSDecimalNumber *factor = [one decimalNumberBySubtracting:[NSDecimalNumber decimalNumberWithDecimal:[client.PricingDiscount decimalValue]]];
NSDecimalNumber *showPrice = [sku.RetailPrice decimalNumerByMultiplying:factor];
falconcreek
I'd suggest creating an NSDecimalNumber from an NSString value of @"100" for the first line, in order to avoid any floating point errors from creeping in.
Brad Larson
Conversion from an int to an NSDecimalNumber is lossless even with floating point, in this case--100 is directly representable by all the primitive types, including `double` and `float`.
Jonathan Grynspan