How can I round a float (such as 37.777779) to two decimal places (37.78) in C?
相关问题
- Multiple sockets for clients to connect to
- What is the best way to do a search in a large fil
- glDrawElements only draws half a quad
- Index of single bit in long integer (in C) [duplic
- Equivalent of std::pair in C
Also, if you're using C++, you can just create a function like this:
You can then output any double
myDouble
withn
places after the decimal point with code such as this:You can still use:
example:
How about this:
Always use the
printf
family of functions for this. Even if you want to get the value as a float, you're best off usingsnprintf
to get the rounded value as a string and then parsing it back withatof
:I say this because the approach shown by the currently top-voted answer and several others here - multiplying by 100, rounding to the nearest integer, and then dividing by 100 again - is flawed in two ways:
To illustrate the first kind of error - the rounding direction sometimes being wrong - try running this program:
You'll see this output:
Note that the value we started with was less than 0.015, and so the mathematically correct answer when rounding it to 2 decimal places is 0.01. Of course, 0.01 is not exactly representable as a double, but we expect our result to be the double nearest to 0.01. Using
snprintf
gives us that result, but usinground(100 * x) / 100
gives us 0.02, which is wrong. Why? Because100 * x
gives us exactly 1.5 as the result. Multiplying by 100 thus changes the correct direction to round in.To illustrate the second kind of error - the result sometimes being wrong due to
* 100
and/ 100
not truly being inverses of each other - we can do a similar exercise with a very big number:Our number now doesn't even have a fractional part; it's an integer value, just stored with type
double
. So the result after rounding it should be the same number we started with, right?If you run the program above, you'll see:
Oops. Our
snprintf
method returns the right result again, but the multiply-then-round-then-divide approach fails. That's because the mathematically correct value of8631192423766613.0 * 100
,863119242376661300.0
, is not exactly representable as a double; the closest value is863119242376661248.0
. When you divide that back by 100, you get8631192423766612.0
- a different number to the one you started with.Hopefully that's a sufficient demonstration that using
roundf
for rounding to a number of decimal places is broken, and that you should usesnprintf
instead. If that feels like a horrible hack to you, perhaps you'll be reassured by the knowledge that it's basically what CPython does.Code definition :
Results :
Use
float roundf(float x)
."The round functions round their argument to the nearest integer value in floating-point format, rounding halfway cases away from zero, regardless of the current rounding direction." C11dr §7.12.9.5
Depending on your
float
implementation, numbers that may appear to be half-way are not. as floating-point is typically base-2 oriented. Further, precisely rounding to the nearest0.01
on all "half-way" cases is most challenging.Although "1.115" is "half-way" between 1.11 and 1.12, when converted to
float
, the value is1.115000009537...
and is no longer "half-way", but closer to 1.12 and rounds to the closestfloat
of1.120000004768...
"1.125" is "half-way" between 1.12 and 1.13, when converted to
float
, the value is exactly1.125
and is "half-way". It rounds toward 1.13 due to ties to even rule and rounds to the closestfloat
of1.129999995232...
Although "1.135" is "half-way" between 1.13 and 1.14, when converted to
float
, the value is1.134999990463...
and is no longer "half-way", but closer to 1.13 and rounds to the closestfloat
of1.129999995232...
If code used
Although "1.135" is "half-way" between 1.13 and 1.14, when converted to
float
, the value is1.134999990463...
and is no longer "half-way", but closer to 1.13 but incorrectly rounds tofloat
of1.139999985695...
due to the more limited precision offloat
vs.double
. This incorrect value may be viewed as correct, depending on coding goals.