Stop Float value rounding off in objective c - ios

I have to prevent the value from rounding off after the decimal.
Here is the code I use :
NSNumberFormatter* nf = [[[NSNumberFormatter alloc] init] autorelease];
nf.positiveFormat = #"0.###";
NSString* trimmedValue = [nf stringFromNumber: [NSNumber numberWithFloat:[exRateLabel doubleValue]*amount]];
trimmedValue = [trimmedValue substringToIndex:[trimmedValue length]-1];
In this case, if I multiply 1000 * 50.1234 I'm getting 50123.3984, but it should be 50123.4.
NSLog(#".2f",50.1234*1000);
For this case it's showing the correct value but for
NSLog(#".2f",50.1234*123);
it is rounding off the actual value, which is 6165.1782, to 6165.18.

Just use double instead of float and a proper rounding rule:
NSNumberFormatter* nf = [[NSNumberFormatter alloc] init];
nf.positiveFormat = #"0.###";
nf.roundingMode = NSNumberFormatterRoundFloor;
NSString* trimmedValue = [nf stringFromNumber: [NSNumber numberWithDouble:50.1234*123]];
NSLog(#"trimmedValue: %#", trimmedValue);
And the result is:
trimmedValue: 6165.178

If the mathematics is required to be precise, I'd suggest using an NSDecimalNumber.
NSDecimalNumber *myNumber = [[NSDecimalNumber alloc] initWithMantissa:501234 exponent:-4 isNegative:NO]];
NSDecimalNumber *answer = [self multiplyDecimalNumber:myNumber with:[NSDecimalNumber decimalNumberWithMantissa:1000 exponent:0 isNegative:NO];
NSLog(#"Answer: %g", floor([answer doubleValue]));
I made a quick wrapper for the multiplication, I never wanted an exception, your needs may be different:
-(NSDecimalNumber *) multiplyDecimalNumber:(NSDecimalNumber *) lhs with:(NSDecimalNumber *) rhs {
NSDecimalNumberHandler *handler = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundPlain scale:NSDecimalNoScale raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO];
return [lhs decimalNumberByMultiplyingBy:rhs withBehavior:handler];
}

They are both correct.
First, I believe you have a typo - you're missing the %.
NSLog(#"%.2f", 50.1234*1000); // same as #"%.2f", 50,123.4 = #"50123.4"
the math leaves you with a clean 1/10th, even though you are asking for 2 decimal places to be printed.
NSLog(#"%.2f",50.1234*123); // same as #"%.2f", 5,161.1782 = #"5161.18"
you are asking for two decimal numbers and rounding up is the default behavior.
It sounds like the formatting you actually want to use is:
NSLog(#"%.1f", number);
or if you want a forced, zero-padded two digits, use
NSLog(#"%.02", number); // first case would come out #"50123.40"
this will force all trailing zeros to be printed

you are probably using a 'double' representation, cast the number to a float or you can use your own policy for truncation using functions like:
float roundUp (float value, int digits) {
int mod = pow(10, digits);
float roundedUp = value;
if (mod != 0) {
roundedUp = ceilf(value * mod) / mod;
}
return roundedUp;
}
float roundDown (float value, int digits) {
int mod = pow(10, digits);
float roundedDown = value;
if (mod != 0) {
roundedDown = floorf(value * mod) / mod;
}
return roundedDown;
}
float nearestf (float value, int digits) {
int mod = pow(10, digits);
float nearest = value;
if (mod != 0) {
nearest = floorf(value*mod + 0.5) / mod;
}
return nearest;
}
'roundUp' should be the one you need, or try with the more generic 'nearestf'

For me it was requirement to show atleast two decimal and maximum decimal number.
Following code did worked for me.
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc] init];
[numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
[numberFormatter setMaximumFractionDigits:2];
[numberFormatter setMinimumFractionDigits:2];
[numberFormatter setRoundingMode:NSNumberFormatterRoundDown];
NSString *num = #"123456.019";
NSString *stringFromNumber = [numberFormatter stringFromNumber:[numberFormatter numberFromString:num]];
NSLog(#"check this %#", stringFromNumber);

Related

How to format a float value in Objective-C

- (NSString *)_stringToFloat:(NSNumber *)number {
if (number && number > 0) {
return [NSString stringWithFormat:#"%.2f",[number floatValue]];
}
return #"0.0";
}
Using:
_lblAppointmentFee.text = [[NSString alloc]initWithFormat:#"%#",[self_stringToFloat:[_dicObject objectForKeyNotNull:#"rate"]]];
How can I can return "5.21" for a value of 5.21 and return "5" for a value of 5.00?
Use an NSNumberFormatter. Set the desired fraction digits.
NSNumberFormatter *nf = [[NSNumberFormatter alloc] init];
nf.numberStyle = NSNumberFormatterDecimalStyle;
nf.minimumFractionDigits = 0;
nf.maximumFractionDigits = 2;
NSString *result = [nf stringFromNumber:#(5.12)];
This gives a result of "5.12" while:
result = [nf stringFromNumber:#(5.00)];
gives a result of "5".
This also has the added bonus of properly formatting the result based on the user's locale.

Is there any easy way to round a float with one digit number in objective c?

Yes. You are right. Of Course this is a duplicate question. Before flag my question, please continue reading below.
I want to round a float value, which is
56.6748939 to 56.7
56.45678 to 56.5
56.234589 to 56.2
Actually it can be any number of decimal precisions. But I want to round it to nearest value. (If it is greater than or equal to 5, then round up and if not, then round down).
I can do that with the below code.
float value = 56.68899
NSNumberFormatter *numberFormatter = [[NSNumberFormatter alloc]init];
[numberFormatter setMaximumFractionDigits:1];
[numberFormatter setRoundingMode:NSNumberFormatterRoundUp];
NSString *roundedString = [numberFormatter stringFromNumber:[NSNumber numberWithFloat:value]];
NSNumber *roundedNumber = [NSNumber numberFromString:roundedString];
float roundedValue = [roundedNumber floatValue];
Above code looks like a long process. I have several numbers to round off. So this process is hard to convert a float value into NSNumber and to NSString and to NSNumber and to float.
Is there any other easy way to achieve what I asked ?
I still have a doubt in the above code. It says roundUp. So when it comes to roundDown, will it work?
Can't you simply multiply by 10, round the number, then divide by 10?
Try
CGFloat float1 = 56.6748939f;
CGFloat float2 = 56.45678f;
NSLog(#"%.1f %.1f",float1,float2);
56.7 56.5
EDIT :
float value = 56.6748939f;
NSString *floatString = [NSString stringWithFormat:#"%.1f",floatValue];
float roundedValue = [floatString floatValue];
NSString* strr=[NSString stringWithFormat: #"%.1f", 3.666666];
NSLog(#"output is: %#",strr);
output is:3.7
float fCost = [strr floatValue];
This works for me
NSNumberFormatter* formatter = [[NSNumberFormatter alloc] init];
[formatter setMaximumFractionDigits:1];
[formatter setMinimumFractionDigits:0];
CGFloat firstnumber = 56.6748939;
NSString *result1 = [formatter stringFromNumber:[NSNumber numberWithFloat:firstnumber]];
NSLog(#"RESULT #1: %#",result1);
CGFloat secondnumber = 56.45678;
NSString *result2 = [formatter stringFromNumber:[NSNumber numberWithFloat:secondnumber]];
NSLog(#"RESULT #2: %#",result2);
CGFloat thirdnumber = 56.234589;
NSString *result3 = [formatter stringFromNumber:[NSNumber numberWithFloat:thirdnumber]];
NSLog(#"RESULT #2: %#",result3);
You don't want float, because that only gives you six or seven digits precision. You also don't want CGFloat, because that only gives you six or seven digits precision except on an iPad Air or iPhone 5s. You want to use double.
Rounding to one digit is done very simply:
double x = 56.6748939;
double rounded = round (10 * x) / 10;
You can use
[dictionaryTemp setObject:[NSString stringWithFormat:#"%.1f",averageRatingOfAllOrders] forKey:#"AvgRating"];
%.1f will give us value 2.1 only one digit after decimal point.
Try this :
This will round to any value not limited by powers of 10.
extension Double {
func roundToNearestValue(value: Double) -> Double {
let remainder = self % value
let shouldRoundUp = remainder >= value/2 ? true : false
let multiple = floor(self / value)
let returnValue = !shouldRoundUp ? value * multiple : value * multiple + value
return returnValue
}
}

NSNumber to float Value

When I convert NSNumber to float value using 'floatValue', there is a difference in precision. Example, I have a NSNumber 'myNumber' having value 2.3, and if I convert myNumber to float using 'floatValue', its value becomes, 2.29999. But I need exactly 2.30000. There is no problem with number of zeros after 2.3, I need '2.3' instead of '2.9'.
How can I do so?
I had similar situation where I was reading value and assigning it back to float variable again.
My Problem statement:
NSString *value = #"553637.90";
NSNumber *num = #([value floatValue]); // 1. This is the problem. num is set to 553637.875000
NSNumberFormatter *decimalStyleFormatter = [[NSNumberFormatter alloc] init];
[decimalStyleFormatter setMaximumFractionDigits:2];
NSString *resultString = [decimalStyleFormatter stringFromNumber:num]; // 2. string is assigned with rounded value like 553637.88
float originalValue = [resultString floatValue]; // 3. Hence, originalValue turns out to be 553637.88 which wrong.
Following worked for me after changing lines:
NSNumber *num = #([value doubleValue]); // 4. doubleValue preserves value 553637.9
double originalvalue = [resultString doubleValue]; // 5. While reading back, assign to variable of type double, in this case 'originalValue'
I hope this would be helpful. :)
If you need exact precision, don't use float. Use a double if you need better precision. That still won't be exact. You could multiply myNumber by 10, convert to an unsigned int and perform your arithmetic on it, convert back to a float or double and divide by 10 and the end result might be more precise. If none of these are sufficiently precise, you might want to look into an arbitrary precision arithmetic library such as GNU MP Bignum.
I've done the following but it is showing me correctly
NSNumber *num = [NSNumber numberWithFloat:2.3];
float f = [num floatValue];
NSLog(#"%f", f);
You can play with something like this:
float x = 2.3f;
NSNumber *n = [NSNumber numberWithFloat:x];
NSNumberFormatter *fmt = [[NSNumberFormatter alloc] init];
[fmt setPositiveFormat:#"0.#"];
NSString *s = [fmt stringFromNumber:n];
float f = [s floatValue];

iOS: NSDecimalNumber: not getting expected results

Say I have the following values for these ivars:
NSString* percentage = 35
NSString* value = 146
In my code below I am expecting to get 51.1 when I do my multiplication (146*.35) but instead am getting 100.
- (NSDecimalNumber*) getProductByPercentage : (NSArray*) itemsToMultiply : (float) annualPatients {
//get items from array
NSString* percentage = [itemsToMultiply objectAtIndex:0];
NSString* value = [itemsToMultiply objectAtIndex:1];
//init a number formatter
NSNumberFormatter * f = [[NSNumberFormatter alloc] init];
//set its formatting style
[f setNumberStyle:NSNumberFormatterDecimalStyle];
//convert to percentage
float thisPercentage = [percentage floatValue]/100;
//convert to NSDecimal
NSDecimalNumber* decPercentage = [[NSDecimalNumber alloc] initWithString:[NSString stringWithFormat:#"%f", thisPercentage]];
NSDecimalNumber* decAvgReimbursement = [[NSDecimalNumber alloc] initWithString: value];
NSDecimalNumber* decAnnualPatients = [[NSDecimalNumber alloc] initWithString:[NSString stringWithFormat:#"%f", annualPatients]];
//set up handler
NSDecimalNumberHandler *handler = [NSDecimalNumberHandler decimalNumberHandlerWithRoundingMode:NSRoundPlain
scale:-2
raiseOnExactness:NO
raiseOnOverflow:NO
raiseOnUnderflow:NO
raiseOnDivideByZero:NO
];
//get our results
NSDecimalNumber* decAvgCost = [decAvgReimbursement decimalNumberByMultiplyingBy:decPercentage
withBehavior:handler];
NSLog(#"%#::%#::%#", decAvgCost, decAvgReimbursement, decPercentage);
return decAvgCost;
}
Here's my log output
2013-02-04 13:57:46.960 EUS Calculator[34154:c07] 100::146::0.35
Is there something wrong with my handler that is getting me the wrong results?
scale:-2
You're setting the scale to round to -2 decimals, that is to the closest 100.
You're rounding to the wrong scale. Try changing the scale to 0 (removes decimal point) and try again. If you want 1 decimal place, use a scale of 1; you should get 51.1 then.
Change this:
float thisPercentage = [percentage floatValue]/100;
to this:
float thisPercentage = [percentage floatValue]/100.0;
If you don't put the .0, then the compiler interprets it as an integer number, and when doing float/int it will convert it to int, transforming your expected 0.35 to 0.
Also, you aren't using your NSNumberFormatter anywhere, so you might as well not even create it.
Why are you using NSDecimalNumbers anyways?

No zero before the decimal point or after second decimal

I have simple calculating in my app
-(IBAction)calculate {
NSNumberFormatter *nf = [[NSNumberFormatter alloc] init];
[nf setRoundingMode: NSNumberFormatterRoundHalfUp];
[nf setMaximumFractionDigits: 2];
float value1 = [[nf numberFromString: textField1.text] floatValue];
float value2 = [[nf numberFromString: textField2.text] floatValue];
float x = value1 * value2 / 100;
label2.text = [nf stringFromNumber: [NSNumber numberWithFloat: x]];
[nf release];
}
Now, when I calculate result looks like this: ,75 or 64,5
I need to my result looks like this: 0,75 or 64,50
My problem is there no zero before the decimal point or after second decimal
Where you set your text in the UILabel, use
label2.text = [NSString stringWithFormat:#"%.2f",x];
This will ensure you get 2 decimal places. You don't even need a number formatter.

Resources