I can't get the correct value of 15136704000
for the third print line and I am not sure what the issue is. It works correctly when compiled via gcc
on Linux
but Windows
keeps spitting out nonsense and I just would like to understand why.
Windows displays it as Which is 2251802112 inches away.
#include <stdio.h>
int main(void)
{
const int five = 5;
const int eight = 8;
const int mi_to_in = 63360;
int miles_to_moon = 238900;
int km_to_moon = (float) eight / five * miles_to_moon;
unsigned long inches_to_moon = (long) miles_to_moon * mi_to_in;
printf("The moon is %d miles away.\n", miles_to_moon);
printf("Which is equivalent to %d kilometers away.\n", km_to_moon);
printf("Which is %lu inches away.\n", inches_to_moon);
}
CodePudding user response:
As commented by @jamesdlin, the expression (long)miles_to_moon * mi_to_in
causes an arithmetic overflow on Windows because the type long
only has 32 bits on this system, including on its 64-bit version. Using unsigned long long
for this computation would solve the problem, and you should actually use long
for mi_to_in
and miles_to_moon
for portability to some systems.
The C Standard provides fixed length integer types such as int32_t
and int64_t
defined in <stdin.h>
on systems that support them. These types could be used for these variables with the proper range, but for better portability and simplicity, you should use double
for such computations:
#include <stdio.h>
int main() {
double mi_to_in = 63360; /* exact figure */
double mi_to_km = 1.60934; /* exact figure */
double miles_to_moon = 238900; /* average distance approximation */
double km_to_moon = miles_to_moon * mi_to_km;
double inches_to_moon = miles_to_moon * mi_to_in;
printf("The moon is %.0f miles away.\n", miles_to_moon);
printf("Which is equivalent to %.0f kilometers away.\n", km_to_moon);
printf("Which is %.0f inches away.\n", inches_to_moon);
return 0;
}
Output:
The moon is 238900 miles away.
Which is equivalent to 384471 kilometers away.
Which is 15136704000 inches away.
Note however that multiplying an approximate figure by an exact one does not increase the precision, which the number of significant digits in the above output might suggest. Rounding these figures seems preferable, yet this would produce 384500 km, which is not the commonly used figure 384400 km.
A more precise average semi-axis is 384399 km, approximately 238855 miles, commonly converted to 238900 mi.
Rounding to a specified number of significant digits is not simple and there is no standard function in the C library to do it. You can use snprintf
with %.3e
to produce the digits in exponential format, and convert back using strtod
, but is cumbersome and inefficient.