I suspect you don't actually have that problem - I suspect you've really got:
double a = callSomeFunction();
// Examine a in the debugger or via logging, and decide it's 3669.0
// Now cast
int b = (int) a;
// Now a is 3668
What makes me say that is that although it's true that many decimal values cannot be stored exactly in float or double, that doesn't hold for integers of this kind of magnitude. They can very easily be exactly represented in binary floating point form. (Very large integers can't always be exactly represented, but we're not dealing with a very large integer here.)
I strongly suspect that your double value is actually slightly less than 3669.0, but it's being displayed to you as 3669.0 by whatever diagnostic device you're using. The conversion to an integer value just performs truncation, not rounding - hence the issue.
Assuming your double type is an IEEE-754 64-bit type, the largest value which is less than 3669.0 is exactly
3668.99999999999954525264911353588104248046875
So if you're using any diagnostic approach where that value would be shown as 3669.0, then it's quite possible (probable, I'd say) that this is what's happening.
Answer from Jon Skeet on Stack OverflowI suspect you don't actually have that problem - I suspect you've really got:
double a = callSomeFunction();
// Examine a in the debugger or via logging, and decide it's 3669.0
// Now cast
int b = (int) a;
// Now a is 3668
What makes me say that is that although it's true that many decimal values cannot be stored exactly in float or double, that doesn't hold for integers of this kind of magnitude. They can very easily be exactly represented in binary floating point form. (Very large integers can't always be exactly represented, but we're not dealing with a very large integer here.)
I strongly suspect that your double value is actually slightly less than 3669.0, but it's being displayed to you as 3669.0 by whatever diagnostic device you're using. The conversion to an integer value just performs truncation, not rounding - hence the issue.
Assuming your double type is an IEEE-754 64-bit type, the largest value which is less than 3669.0 is exactly
3668.99999999999954525264911353588104248046875
So if you're using any diagnostic approach where that value would be shown as 3669.0, then it's quite possible (probable, I'd say) that this is what's happening.
main() {
double a;
a=3669.0;
int b;
b=a;
printf("b is %d",b);
}
output is :b is 3669
when you write b=a; then its automatically converted in int
see on-line compiler result :
http://ideone.com/60T5b
This is called Implicit Type Conversion Read more here https://www.geeksforgeeks.org/implicit-type-conversion-in-c-with-examples/
c - how to truncate a number with a decimal point into a int? what's the function for this? - Stack Overflow
c++ - Truncating double without rounding in C - Stack Overflow
How can I safely truncate a signed integer?
double to int conversion - C++ Forum
It truncates automatically is you assign value to "int" variable:
int c;
c = a/b;
Or you can cast like this:
c = (int) (a/b);
This truncates it even if c is defined as float or double.
Usually truncation is not the best (depends what you want to achieve of course). Usually result is rounded like this:
c= round(a/b,0);
is more intelligent because rounds result properly. If you use linux, you can easily get reference with "man round" about exact data types etc.
You can use the trunc() function defined in math.h. It will remove fractional part and will return nearest integer not larger than the given number.
This is how it is defined:
double trunc(double x);
Below is how you can use it:
double a = 18.67;
double b = 3.8;
int c = trunc(a/b);
You can check man trunc on Linux to get more details about this function. As pointed out in previous answers, you can cast division result to integer or it will automatically be truncated if assigned to integer but if you were interested to know about a C function which does the job then trunc() is the one.
How can I safely convert a long to int by discarding all bits beyond 33? If I simply cast, if the value in the long cannot be represented in int (i.e. overflows), the behavior is undefined. How can I get around this? I could cast them to unsigned prior to truncation, but then how can I safely convert unsigned int to int without invoking undefined behavior if the MSB is set? Is the following undefined behavior:
(int)(unsigned int)(int){-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.
Casting is not a mathematical operation and doesn't behave as such. Try
int y = lround(x);
round(d*10000.0)/10000.0;
or if p must be variable;
double f = pow(10,p);
round(d*f)/f;
round will usually be compiled as a single instruction that is faster than converting to an integer and back. Profile to verify.
Note that a double may not have an accurate representation to 4 decimal places. You will not truly be able to truncate an arbitrary double, just find the nearest approximation.
Efficiency depends on your platform.
Whatever methods you try, you should profile to make sure
- the efficiency is required (and a straightforward implementation is not fast enough for you)
- the method you're trying is faster than others for your application on real data
You could multiply by 10000, truncate as an integer, and divide again. Converting between double and int might be faster or slower for you.
You could truncate on output, e.g. a printf format string of "%.4f"