Rich Apodaca
Rich Apodaca

Reputation: 29004

Get exponent of NSDecimalNumber in Objective-C?

Given an NSDecimalNumber, how can I find the exponent (scale)?

Although it should in principle be possible to do this by first converting to an NSString followed by some ugly string manipulation, I'd rather avoid it.

With a Java BigDecimal, I can call the scale() method to get the scale.

Does a similarly concise method exist for NSDecimalNumber?

Upvotes: 8

Views: 1552

Answers (5)

Lukas Kalinski
Lukas Kalinski

Reputation: 2243

If you want to have the expression to be on base-10 form (frexp(3) seems to only do base-2), you could try this:

double mantissa = [someDecimalNumber doubleValue];
int exp = 0;

if (mantissa >= 1.0f) {
    while (mantissa >= 1.0f) {
        mantissa = mantissa / 10.0f;
        exp++;
    }
} else {
    while (mantissa*10.0f < 1.0f) {
        mantissa = mantissa * 10.0f;
        exp--;
    }
}

NSLog(@"%f = %f x 10^%d", [someDecimalNumber doubleValue], mantissa, exp);

Upvotes: 0

Jason Coco
Jason Coco

Reputation: 78353

If you really need the exponent for some reason (other than simply display, which you can configure a number formatter to give you), you can get the primitive double with the -doubleValue method and then use frexp(3) to get the mantissa and exponent values.

The whole design behind objects for doing and storing floating point math is that you can handle computational and precision errors more effectively, however, the limitation of that design is once you convert from a scalar (such as a double or the combination of a mantissa and exponent), you are expected to stay within the object framework and not convert back to a (potentially) less precise format.

I suggest using the -doubleValue is the best option, since other answers suggest accessing private structure records which may change, and using these suggests no precision loss, when, in fact, there very well may be (as documented in the header files). When converting to a double, you and those who use/read your code know exactly what precision errors may be possible because the type is very well understood and very well documented.

Finally, if you want to be sure if a conversion is going to cause an error, you can create and use an NSDecimalNumberHandler which will give you information about what kind of rounding/precision errors you can expect when converting to the double scalar type.

I also suggest you add an enhancement request using the apple bug reporter stating that you'd like access to the exponent directly as well as possibly adding a higher precision type, like a -longDoubleValue method.

Edit includes more information

Upvotes: 3

Sulthan
Sulthan

Reputation: 130102

You can compare the number with NSDecimalNumber instances created with mantissa equal to 1, changing the exponent. It can work like a binary search.

Upvotes: -1

leo
leo

Reputation: 7656

You can access it on NSDecimal:

int exponent = decimalNumber.decimalValue._exponent;

Upvotes: 2

Tim
Tim

Reputation: 60110

No, it doesn't look like NSDecimalNumber has an equivalent. I think you may have to write your own.

If you don't mind digging around a bit (and ignoring documentation warnings), however, you might look at the NSDecimal structure that gets returned from -decimalValue - it has a number of fields that you could probably get to. Whether this is subjectively better or worse than your NSString manipulations is up to you.

Upvotes: 1

Related Questions