How to split a NSDecimalnumber between decimal & integer & back
Asked Answered
G

4

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?


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.


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...

Gasbag answered 28/1, 2009 at 16:38 Comment(0)
B
20

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:0 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.

Bactericide answered 29/1, 2009 at 14:39 Comment(2)
should it not be 0 for scale? Using a scale of 2, a price of 10.5 will round giving dollars of 10.5. Subtracting that from price will give cents of 0Oppress
I believe this doesn't work when the number is negative, since RoundDown rounds away from zero then according to <developer.apple.com/reference/foundation/…>. And would be simple to switch between Up or Down rounding modes based on negative value except testing for a negative value is not straightforward, easiest to do num.doubleValue >= 0. At least Decimal in Swift exposes a sign property.Diesel
C
0

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

Cadaver answered 28/1, 2009 at 17:1 Comment(0)
P
0

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;
Peptone answered 28/1, 2009 at 19:5 Comment(0)
P
-1

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
Piperpiperaceous answered 28/1, 2009 at 21:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.