Re: working with NSDecimalNumber and NSNumber
Re: working with NSDecimalNumber and NSNumber
- Subject: Re: working with NSDecimalNumber and NSNumber
- From: William Squires <email@hidden>
- Date: Sun, 2 Jul 2006 19:05:23 -0500
On Jun 24, 2006, at 5:01 PM, Derrick Bass wrote:
On Jun 23, 2006, at 10:34 AM, email@hidden wrote:
Hi list
I was wondering what was the most efficient way to process
calculations between an NSNumber and an NSDecimalNumber
should I use :
NSNumber *myNormalNumber;
NSDecimalNumber *myDecimalNumber;
[...]
myDecimalNumber = [myDecimalNumber
decimalNumberByMultiplyingBy:[NSDecimalNumber
decimalNumberWithString:[myNormalNumber stringValue]]];
or
myDecimalNumber = [myDecimalNumber
decimalNumberByMultiplyingBy:[NSDecimalNumber
decimalNumberWithDecimal:[myNormalNumber decimalValue]]];
(documentation says that decimalValue's value returned isn’t
guaranteed to be exact for float and double values)
Right, that's because floats and doubles are base-2 while
NSDecimalNumber is base-10. Now it is possible to represent any base-2
value exactly as an decimal number, but NSDecimalNumber doesn't have
enough precision to be able to do that always for doubles. Moreover,
it is likely that whatever is in your float or double is rounded off
already. You won't get any more precision by converting to strings
(less, I should think). If you really need to multiply by a
non-integer float or double, there's really nothing to be done; you'll
just have to accept the precision loss.
And, actually, this occurs even in real life, not just in computers.
Any (real) number has to be representable in some base >= 2. The number
will be exactly representable in that base as long as its factors are
multiples of the base.
So any rational number n/d will be exactly representable in base 10
as long as both 'n' and 'd' have factors of 2 and or 5, or integral
powers thereof. Ditto for some other base. So 1/3 isn't exactly
representable as a decimal (base 10) number because 3 isn't a factor of
10.
So the only way to represent ANY real number without losing precision
would be to use base infinity, which would clearly be impractical! :)
Furthermore, why p*ss around with NSNumbers and such if you're
dealing with currency? Just convert the numbers to cents and store in a
long int. Do the calculations there (a lot faster), then convert back
to an NSNumber or NSDecimalNumber, remembering that you're storing
cents, not dollars.
The same goes for other nation's currencies - just represent the
smallest denomination in an integral data type.
Be careful multiplying (or dividing) fractions (like when calculating
interest, APR, etc...) For example: 3 cents x 3 cents is clearly 9
cents, but $0.03 x $0.03 = $0.0009, or 9 one-hundredths of a penny.
Whoops.
or should I use parent methods From NSNumber like numberWithFloat: ?
I use NSDecimalNumber for money related values so my calculations
need to be as precise as possible ...
Are you sure you aren't actually multiplying by a decimal number? If
so, then you should represent it exactly in an NSDecimalNumber. If
your numbers really are floats (like from an interest calculation)
then you'll have to decide upon an appropriate rounding scheme. And if
it really is a decimal number, but you just can't help the fact that
it is represented by a float/double, then convert it to an
NSDecimalNumber and round it to the correct number of places before
calculating with it.
Derrick
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden
William H Squires Jr
4400 Horizon Hill #4006
San Antonio, TX 78229
email@hiddenm <- remove the .nospam
_______________________________________________
Do not post admin requests to the list. They will be ignored.
Cocoa-dev mailing list (email@hidden)
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden