views:

1015

answers:

7

I can't figure how get the integral & decimal value from a NSDecimalnumber.

For example, if I have 10,5, how get 10 & 5?

And if I have 10 & 5, how return to 10,5?

+1  A: 

Not sure what Math functions objective c has but something like

Math.floor(10.5) = 10
(10.5 - 10) * 10 = 5

bit of a clearer example (cos of the 10's)

Math.floor(20.4) = 20
(20.4 - 20) * 10 = 4;

The other problem

(5 / 10) = .5
10 + .5 = 10.5

The 10 used on the decimal points depends on the amount of decimal places... for instance

Math.floor(20.44) = 20
(20.44 - 20) * 100 = 44;

requires you to times by 100

James Hay
+1  A: 

If you don't have access to the math fns, this may work:

double val = [dn doubleValue]; // dn is a NSDecimalNumber*
int intPart = (int) val;
double doublePart = (val - intPart);

This may give you some trouble, the loop may never terminate, in that case you will have to put a counter in there:

while (doublePart != (int)doublePart) doublePart*=10;
Fredrik Jansson
A: 

double floor (double x); is a POSIX function. This function can be used to find the highest integer value not greater than x.

double x = 10.5;

double y = floor (x);
// y = 10.0

double z = x - y;
// z = 0.5
dreamlax
A: 

Mmm ok, that is the way, but not respect the # of decimal places. If exist a way to know that from the current local I'm set.

This is because that represent currency values...

mamcx
+2  A: 

The underlying procedure is correct. You just need to use NSDecimalNumber's methods to preserve precision:

NSDecimalNumber *price = /*...*/;
NSDecimalNumber *dollars = [price decimalNumberByRoundingAccordingToBehavior:NSRoundDown];
NSDecimalNumber *cents = [price decimalNumberBySubtracting:dollars];
Peter Hosey
+4  A: 

Peter's method is nearly complete but you can't use NSRoundDown directly as a behavior. You'll need something like this instead. I'm using 2 for the scale since you said this was for currency but you may choose to use another rounding scale. I'm also ignoring any exceptions rounding may bring since this is a pretty simple example.

NSDecimalNumberHandler *behavior = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundDown scale:2 raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO];
NSDecimalNumber *price = /* eg. 10.5 */;
NSDecimalNumber *dollars = [price decimalNumberByRoundingAccordingToBehavior: behavior];
NSDecimalNumber *cents = [price decimalNumberBySubtracting: dollars];

That will give you 10 and 0.5 in the dollars and cents variables respectively. If you want whole numbers you can use this method to multiply your cents by a power of 10.

cents = [cents decimalNumberByMultiplyingByPowerOf10: 2];

Which will in turn multiply you cents by 100, giving you 10 and 5 in dollars and cents. You should also know that you can use negative powers of 10 here to divide.

So,

cents = [cents decimalNumberByMultiplyingByPowerOf10: -2];

would undo that last method.

Ashley Clark
A: 

Mmm ok, that is looking better!

However I have the concer about lossing decimals.

This is for a app that will be international. If for example a user set the price "124,2356" I wanna load & save the exact number.

mamcx
That won't be a problem except for a LOT of decimal places. (Read the documentation to find out exactly how many.) Also, post these as comments or question edits, as you are not answering your own question.
Peter Hosey