views:

854

answers:

4

I'm converting an algorithm I wrote in Java to Objective-C. In java the BigDecimal class handles base-10 numbers and can take the primitive double as a constructor arg. In Cocoa's NSDecimalNumber class, however, there is no direct way to construct an instance using a primitive double.

Currently I'm using this (smelly) hack:

    [NSDecimalNumber decimalNumberWithString:[NSString stringWithFormat:@"%1.38f", number]];

Is there a better way?

+8  A: 

NSNumber, the superclass of NSDecimalNumber, has a +numberWithDouble: method. That's what you want.

Chuck
Wow, how'd I miss that. Thanks.
Mike Reedell
NSDecimalNumber numberWithDouble is the same method as NSNumber numberWithDouble. It will return NSNumbers and not NSDecimalNumbers (see my other comments about this).
Danny Tuppeny
@Danny Tuppeny: I just tested this and you appear to be wrong. I did `[[NSDecimalNumber numberWithDouble:12.7] class]` and got back NSDecimalNumber. The error you refer to in your other comment is a static typing error in Cocoa AFAICT. The dynamic type is fine and works normally. The fact that `numberWithDouble:` only exists on NSNumber is irrelevant, since it just calls `[[[self alloc] initWithDouble:double] autorelease]`, and `self` is whichever class received the message. This is basic inheritance — classes can inherit their parents' convenience constructors.
Chuck
Incidentally, for anyone interested, there was some discussion on the Cocoa-Dev mailing list a while back about the issue that Danny brings up. Basically, this is just different engineers using different styles in their headers and not foreseeing the consequences. The static-typing style of NSNumber's convenience constructors gives a little more static type protection (obviously) but leads to spurious errors like this when used with a subclass, so most classes return `id` instead.
Chuck
@Chuck Thanks for the info. I'd spent ages trying to figure out what was happening earlier (I'm relatively new to objective-c, coming from C#). Something to watch out for in future!
Danny Tuppeny
+2  A: 
[NSDecimalNumber numberWithDouble:myDouble]
Ben Alpert
A: 

In other posts I'm finding info that using the NSNumber methods with NSDecimalNumber either will return NSNumber, or will return NSDecimalNumber but that's not what the spec says it should so it may be considered a bug and change in the future. Er something like that.

Futurist
+1  A: 

I've found the way to get this to work, and to dismiss the warning is like this.

    NSNumber *temp = [NSNumber numberWithDouble:self.hourlyRate];
    myDecimal = [NSDecimalNumber decimalNumberWithDecimal:[temp decimalValue]]; 

It gets rid of the warning, albeit being two lines instead of one.

Yakattak