29

I have a

float a = 1412.244019;

and I need a to be rounded to the nearest second decimal like 1412.24000000. I understand that if i want to present a with only two decimals i use %.2f, but that is NOT the case. I need the new a for mathematical reasons as a float.

I have tried a couple of methods found on stackoverflow without luck. The more obvious one i used, i mention below, but still had no luck using it. Can YOU see why the magic is not happening?

PS: It does do the desired effect sometimes, NOT always, which gets me thinking... hmmm...

Thanks in advance.

Code:

float a = 1412.244019;
NSLog(@"a is %f", a); //output a is 1412.244019
a = [[NSString stringWithFormat:@"%.2f", a] floatValue];
NSLog(@"a is %f", a); //output a is 1412.239990

EDIT:

SEEMS like when i am using the float a after the above surgery, it is considering it to be 1412.240000 eventhough the NSLog says differently... strange. But i am getting what I want, so Kudos for wasted time chasing nothing :)

EDIT I would love to choose you all as correct answers, but since i can only choose one, i chose the first good answer with extra explanation (of the two last).

B-Man
  • 2,209
  • 3
  • 22
  • 35

6 Answers6

60

Have you tried this?

CGFloat val = 37.777779;

CGFloat rounded_down = floorf(val * 100) / 100;   /* Result: 37.77 */
CGFloat nearest = floorf(val * 100 + 0.5) / 100;  /* Result: 37.78 */
CGFloat rounded_up = ceilf(val * 100) / 100;      /* Result: 37.78 */

source : Rounding Number to 2 Decimal Places in C

Complementing: You just don't have control about how the computer will store the float value.

So these rounded values may not be EXACTLY the "obvious" decimal values, but they will be very very close, and that's the max guarantee you will have.

Community
  • 1
  • 1
Lucas Eduardo
  • 11,525
  • 5
  • 44
  • 49
  • Have tried it, Saw you had posted this method in another post. But the NSLog still giving same answer (try urself). But please see EDIT above. Eventhough the NSLog is giving "wrong" format, it is using it correct. – B-Man Aug 05 '13 at 17:23
  • Like I said in the edit, it's impossible to get full precision in float points – Lucas Eduardo Aug 05 '13 at 17:24
  • I understand. It is computing it the way i want to. I just think that is strange, because then you will never be able to use precise arithmetic? – B-Man Aug 05 '13 at 17:26
  • Yes, the precision is usually good enough for perform calculations, and the error smaller enough to be disconsidered – Lucas Eduardo Aug 05 '13 at 17:27
  • Okay. Thanks for your answer and time :) I will go with the results i got. – B-Man Aug 05 '13 at 17:31
  • The end of your answer is wrong. Each of `a` and `b` receives the neatest `CGFloat` to the rational number 377/10. The condition `a == b` is always true. – Pascal Cuoq Aug 05 '13 at 22:59
  • Thanks for pointed it out, it was not a good example to show what I wanted to mean. Edited. – Lucas Eduardo Aug 05 '13 at 23:17
11

You do that in Objective-C exactly the same as you would in C:

double notRounded = ...;
double rounded = round (notRounded * 100.0) / 100.0;

Don't use float - unless you can explain to someone exactly what your specific reasons are to use float over double. float has very limited precision. And using ceil or floor is daft, since there is a perfectly fine standard function named "round".

Neither float nor double can exactly represent most decimal values, like 12.24. Because it has much higher precision, double will let you get much closer to 12.24. Therefore, there is a huge chance that NSLog will display some weird number for (float) 12.24, like 12.23999997394 or whatever, while it may display 12.24 for double.

gnasher729
  • 51,477
  • 5
  • 75
  • 98
  • 1
    Thanks for the answer. Double is the way to go then. I have already chosen an answer some time ago, so i think i can only up your answer. Thanks for your time to explain, much appreciated. – B-Man Mar 20 '14 at 21:02
6

Error in this Line

a = [[NSString stringWithFormat:@"%.2f", a] floatValue];

correct it to

a = [NSString stringWithFormat:@"%.02f", a];
Mitesh Varu
  • 123
  • 1
  • 10
5

The closest value to 1412.24 that a float can have is 1412.239990234375. There is no operation that can produce a float any closer than that, because the format of float objects does not represent any closer values. Asking to represent 1412.24 in float is like asking to represent 2.5 in int. It simply cannot be done.

Options for dealing with this include:

  • You can use use formatting that displays “1412.24”, without changing the underlying float object.
  • You can use double to get closer (much closer), but it will still not be exactly 1412.24.
  • You can scale float values to representable values (e.g., measure in other units so that the values you want are all exactly representable in float).
  • You can use a different data type, such as NSDecimal.
Eric Postpischil
  • 195,579
  • 13
  • 168
  • 312
  • I appreaciate your answer, and I think i will have to find another way. But please see EDIT above. Eventhough the NSLog is giving "wrong" format, it is using it correct. I will see if I get better results using one of your above mentioned methods. – B-Man Aug 05 '13 at 17:32
  • 1
    @B-Man, the C `float` type CAN NOT promise a perfect rounding. If you require that, use another data type. You can Roll Your Own and keep the value in NSInteger value of 100ths, or you can use another data type like the [NSDecimal](https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSDecimalNumber_Class/Reference/Reference.html) listed above. – bshirley Aug 05 '13 at 18:04
2

You could multiply a by 100.0 and perhaps add 0.5 for rounding and then take the int value of the result. You can then use / 100 to get the value before the decimal point and % 100 to get the two decimal places.

David Elliman
  • 1,379
  • 8
  • 15
2

You can't force a float value. Floats are designed to be somewhat approximate, as their magnitude can be great, and since you've only got so many bits to use, it can get close to, but not exactly express a decimal number.

One suggestion is to do all your arithmetic in integer, multiplied by 100, then dividing when you want to display your final result. You may have numbers too large which would prohibit this.

Owen Hartnett
  • 5,925
  • 2
  • 19
  • 35
  • I appreaciate your answer, and I think i will have to find another way. But please see EDIT above. Eventhough the NSLog is giving "wrong" format, it is using it correct. – B-Man Aug 05 '13 at 17:24
  • NSLog is telling you the truth...but you are probably using other formatting/arithmetic that is balancing out (as float arithmetic is designed to do) to get you near the true answer. But you will find that sometimes it does what you expect, and sometimes it has these trailing decimals that shouldn't be there, or the number is just short. It is most pronounced when you go to print the answer, or if you try to compare two floating point numbers (i.e. 2.0 != 5.0 - 3.0). If you need exact, precise arithmetic to always be right to 2 decimal places, you should use integer as above and / 100. – Owen Hartnett Aug 05 '13 at 18:28