简体   繁体   中英

how to save a float to nsnumber with just two decimals

I'm trying to save a float to an nsnumber but i just want to save it with two decimal places. I know I can do it by converting to an NSString first using this code

NSString* formattedNumber = [NSString stringWithFormat:@"%.02f", myFloat];

but seems clumsy. All I want to do is convert

float numb = 23.25454 into NSNumber 23.25

Just round it using any of these functions

float rounded = round(val * 100) / 100;
float rounded_down = floorf(val * 100) / 100;
float nearest = floorf(val * 100 + 0.5) / 100;
float rounded_up = ceilf(val * 100) / 100;

If you're looking for an object oriented approach, try using NSDecimalNumber which is a subclass of NSNumber . Init the NSDecimalNumber with your float value and then call decimalNumberByRoundingAccordingToBehavior: . This gives you a few options of how the truncation or rounding occurs with NSDecimalNumberBehaviors , where you can set the scale (number of digits following the decimal) and an NSRoundingMode. Check the docs for more info.

Use this

float numb = 23.25454;

NSNumber *num = @((int)(numb*100)/100.0);

It is impossible to do this with float , double , or either of those wrapped as an NSNumber . You need to understand how floating point works.

All these use binary numbers, you wish to represent a number with exactly two decimal places. A binary fraction is made up from a sum of 1/2, 1/4, 1/8, 1/16... while a decimal fraction is a sum of 1/10, 1/100, 1/1000... Not all values which can be represented as a sum of values in one of this series can be represented as a sum in the other. This is a similar issue to representing 1/3 in decimal, it is 3/10 + 3/100 + 3/1000 + .....

Try writing, for example, 0.17 = 17/100 = 1/10 + 7/100 as a sum of 1/2, 1/4 etc. Well it's 1/8 + 9/200 = 1/8 + 1/32 + 11/8000 (I'm just doing this on the fly, excuse any errors!) = you figure it out!

To address this there is the NSDecimalNumber class , which is a subclass of NSNumber and represents numbers in base-10. The class provides the basic operations to do base-10 arithmetic. You can't mix arithmetic easily between base-10 and base-2 numbers, you cannot even create an NSDecimalNumber directly from a float or double - you format the later as an NSString (ie convert them to a base-10 representation) - and extracting a double value with the doubleValue method is described as:

The approximate value of the receiver as a double .

Note the approximate .

So a long answer to get to a question: do you really want to store a float or double value to exactly two decimal places?

You can use the round , floor & ceil families to do it approximately, but be prepared for results that are "wrong". Eg try:

float a = 371371.28127;
float b = roundf(a * 100.0) / 100.0;
NSLog(@"a: %f | b: %f", a, b);

HTH

float numb = 23.25454;
float myFloat = roundf(100 * numb) / 100.0;
NSNumber *number = [NSNumber numberWithFloat:myFloat];

NSDecimalNumber with NSDecimalNumberHandler is the best way to get accurate precisions if you want as Object. Below is the sample code.

-(NSDecimalNumber *)getRoundedNumberAfterPointDigitsCount:(int)digitsCount withDouble:(double)doubleValue{
    NSDecimalNumber *decimalNumber = [NSDecimalNumber decimalNumberWithString:[NSString stringWithFormat:@"%f",doubleValue]];
    NSDecimalNumberHandler *decimalHandler = [[NSDecimalNumberHandler alloc] initWithRoundingMode:NSRoundPlain scale:digitsCount raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO];
    decimalNumber =  [decimalNumber decimalNumberByRoundingAccordingToBehavior:decimalHandler];
    return decimalNumber;
}

There is more of Rounding option available with NSRoundingMode.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM