C++: How to round a double to an int?
Solution 1
add 0.5 before casting (if x > 0) or subtract 0.5 (if x < 0), because the compiler will always truncate.
float x = 55; // stored as 54.999999...
x = x + 0.5 - (x<0); // x is now 55.499999...
int y = (int)x; // truncated to 55
C++11 also introduces std::round, which likely uses a similar logic of adding 0.5 to |x| under the hood (see the link if interested) but is obviously more robust.
A follow up question might be why the float isn't stored as exactly 55. For an explanation, see this stackoverflow answer.
Solution 2
Casting is not a mathematical operation and doesn't behave as such. Try
int y = (int)round(x);
Solution 3
Casting to an int
truncates the value. Adding 0.5
causes it to do proper rounding.
int y = (int)(x + 0.5);
Solution 4
It is worth noting that what you're doing isn't rounding, it's casting. Casting using (int) x
truncates the decimal value of x
. As in your example, if x = 3.9995
, the .9995
gets truncated and x = 3
.
As proposed by many others, one solution is to add 0.5
to x
, and then cast.
midnightBlue
Updated on July 11, 2022Comments
-
midnightBlue almost 2 years
I have a double (call it x), meant to be 55 but in actuality stored as 54.999999999999943157 which I just realised.
So when I do
double x = 54.999999999999943157; int y = (int) x;
y = 54 instead of 55!
This puzzled me for a long time. How do I get it to correctly round?
-
Blastfurnace about 12 yearsYou could add 0.5 to the number and then do your cast to let it truncate to an int. Do you need to round negative numbers?
-
c00000fd almost 10 yearsYou can use this preprocessor definition:
#define ROUND_2_INT(f) ((int)(f >= 0.0 ? (f + 0.5) : (f - 0.5)))
-
Ruslan almost 8 yearsActually 54.999999999999943157 is 8 ULPs below exactly representable 55 if by
double
you mean binary64 from IEEE 754. So this is not how 55 is actually stored, it's the consequence of how imprecise your calculation of it was. -
DragonLord over 7 yearsAdding +0.5 to a negative input before turning it into an int will give the wrong answer. The correct quick-and-dirty way is to test the input sign for <0, and then SUBTRACT 0.5 from the negative inputs before turning them into an int. Most of the following answers do not explain this properly. Note high-accuracy procedures should use the new slower "round()" function.
-
Vadzim over 7 years
-
plafratt over 7 yearsFor me, the program to below prints "55". Am I doing something differently than you?
#include<iostream> using namespace std; int main() { float x = 55; int y = (int) x; cout << y; }
-
midnightBlue over 7 years@plafratt It may be possible that your system's implementation of
float
is such thatfloat x = 55
is stored as a value slightly greater than55
instead. In this case(int) x
would seem to 'round down' correctly to55
, and not54
, as in my case. -
plafratt over 7 yearsOh ok. For reference, the code below gives this output: "55 55.00000000000000000000".
#include<iostream> #include<iomanip> using namespace std; int main() { float x = 55; int y = (int) x; cout << y << " " << fixed << setprecision(20) << x << "\n"; }
Changing the "float x = 55;" to "float x = 55.1;" gives me the output "55 55.09999847412109375000" -
raaj about 4 years
-
hgrey almost 4 yearsthe question in not equivalent to referenced question as it asking for type conversion as well
-
-
Keith Thompson about 12 yearsThe cast is unnecessary; the result will be implicitly converted to
int
. -
midnightBlue about 12 yearsit would work equally as well with just int y=x+0.5; though right?
-
MK. about 12 yearsI could never remember the C type promotion rules and I think that it doesn't hurt to state type casts explicitly everywhere, them being such a sticky issue.
-
midnightBlue about 12 yearsThank you, actually I only just realised I even need to round (I am using only integers in my program)
-
Steve Fallows about 12 yearsWhat library is
round
part of? AFAIK it's not in the C++ standard library.ceil
andfloor
are available. -
MK. about 12 years@Steve #include <math.h>, STANDARDS The round() , lround() , and llround() functions conform to ISO/IEC 9899:1999(E).
-
Admin about 12 yearsI wouldn't use the phrase "round down", because that could be interpreted as rounding
-0.5
to-1
. -
Steve Fallows about 12 years@MK - Well that's actually C not C++ right? I referred to this: cplusplus.com/reference/clibrary/cmath
-
GManNickG about 12 years@SteveFallows: It exists in C++11.
-
Keith Thompson about 12 years@MK.: It's not a promotion, it's just an implicit conversion. An assignment, initialization, or parameter passing will implicitly convert any numeric type to any other numeric type. Unnecessary casts can be harmful. For example,
n = (int)round(x);
looks ok -- but what ifn
is of typelong
? -
Verax almost 11 years-1 This method does not take into consideration negative numbers.
-
mehfoos yacoob over 10 yearsnot valid for negative numbers, as mentioned in one of the comments above. Can use 'floor' instead of cast if you are doing this.
-
mehfoos yacoob over 10 yearsAs @Verax mentioned, this does not work for negative numbers as cast truncates toward 0. You may use the same logic with 'floor' instead as it truncates towards -infinity.
-
Nick X Tsui almost 10 yearsThis answer is wrong. It will give you wrong answer if the number is negative.
-
Moritz almost 10 years@NickXTsui did you see the last sentence? "Note that this will not work for negative numbers."
-
Nick X Tsui almost 10 years@Moritz; Oh sorry, I will upvote you. My apologies.
-
Albert Renshaw over 9 yearsThis forces numbers up though... 54.000000000000001 will become 55.
-
Henry Henrinson over 9 years-1 this is a hacky solution at best. zik's answer is much better as it uses a library function: works on negative numbers, doesn't do weird casting and it's explicit about it's intention.
-
Moritz over 9 years@HenryHenrinson
ceil()
/floor()
also adds another level to the call stack (although I suspect that a modern compiler will inline it for you,) makes you include a library header and generally introduces more overhead. I don't think one is necessarily worse than the other without knowing what the OP is trying to accomplish. Also, I don't think casting from floating-point to int explicitly is that "weird"...whether you see it or not, that type conversion has to happen somewhere along the line :) -
Henry Henrinson over 9 years@Moritz One can perform rounding and still return a double. Regardless, the point here is that the code is not explicit about what sort of casting it does. Does it take floor, ceil, rounds it, or does it just interpret the bits at the memory location referenced by the double as ints? Writing the code like this needlessly makes the reader remember what the conversion rules are. I agree that there are places where this code makes sense, but imagine someone googles "how to round c++" and ends on this page. IMO, the best answer for that situation is the one below.
-
cp.engr over 8 years@AlbertRenshaw, right - which means this answer is wrong.
-
jacknad about 8 yearsI prefer positive numbers
-
Ruslan almost 8 yearsWhat do you mean by
stored as stored as 54.999999...
?55
is exactly representable in binary32 from IEEE 754. Its representation is 0x425c0000. As you can see, it's more than exact: It has plenty of digits to store some fractional part you add to it. And it's especially true of0.5
, which is a power of two. -
ACyclic over 7 yearsThis is inaccurate & possibly slow. See clang-tidy for an explanation : clang.llvm.org/extra/clang-tidy/checks/…
-
Pac0 over 5 years@ACyclic unfortunately, the link you provided is dead.
-
ACyclic over 5 years@Pac0 Updated link on why this is inaccurate : releases.llvm.org/5.0.2/tools/clang/tools/extra/docs/clang-tidy/…
-
markokstate almost 5 years@ACyclic That link just states it's bad but doesn't provide any suggestions to the problem.
-
Qiangzini over 4 yearsIn both C99 and C++11,
double round (double x);
Therefore, the cast is indeed necessary. Link:cplusplus.com/reference/cmath/round -
simplename about 2 yearsif you use
std::round(double arg)
cast is necessary; but if you usestd::lround(double arg)
cast is not needed