C unsigned long 转换不正确添加
C unsigned long with casting not adding correctly
我无法获得第三行打印的 15136704000
的正确值,我不确定问题出在哪里。通过 gcc
在 Linux
上编译时它可以正常工作,但是 Windows
一直在胡说八道,我只是想了解为什么。
Windows 显示为 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);
}
正如@jamesdlin 评论的那样,表达式 (long)miles_to_moon * mi_to_in
导致 Windows 上的算术溢出,因为类型 long
在该系统上只有 32 位,包括其 64 位版本。使用 unsigned long long
进行此计算可以解决问题,您实际上应该使用 long
进行 mi_to_in
并使用 miles_to_moon
进行某些系统的可移植性。
C 标准在支持它们的系统上提供固定长度的整数类型,例如 <stdin.h>
中定义的 int32_t
和 int64_t
。这些类型可用于具有适当范围的这些变量,但为了更好的可移植性和简单性,您应该使用 double
进行此类计算:
#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;
}
输出:
The moon is 238900 miles away.
Which is equivalent to 384471 kilometers away.
Which is 15136704000 inches away.
但是请注意,将近似数字乘以精确数字并不会增加精度,上述输出中的有效位数可能表明了这一点。将这些数字四舍五入似乎更可取,但这将产生 384500 公里,这不是通常使用的数字 384400 公里。
更精确的平均值 semi-axis 是 384399 公里,大约 238855 英里,通常转换为 238900 英里。
四舍五入到指定数量的有效数字并不简单,C 库中没有标准函数可以做到这一点。您可以使用 snprintf
和 %.3e
来生成指数格式的数字,然后使用 strtod
转换回来,但是很麻烦且效率低下。
我无法获得第三行打印的 15136704000
的正确值,我不确定问题出在哪里。通过 gcc
在 Linux
上编译时它可以正常工作,但是 Windows
一直在胡说八道,我只是想了解为什么。
Windows 显示为 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);
}
正如@jamesdlin 评论的那样,表达式 (long)miles_to_moon * mi_to_in
导致 Windows 上的算术溢出,因为类型 long
在该系统上只有 32 位,包括其 64 位版本。使用 unsigned long long
进行此计算可以解决问题,您实际上应该使用 long
进行 mi_to_in
并使用 miles_to_moon
进行某些系统的可移植性。
C 标准在支持它们的系统上提供固定长度的整数类型,例如 <stdin.h>
中定义的 int32_t
和 int64_t
。这些类型可用于具有适当范围的这些变量,但为了更好的可移植性和简单性,您应该使用 double
进行此类计算:
#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;
}
输出:
The moon is 238900 miles away.
Which is equivalent to 384471 kilometers away.
Which is 15136704000 inches away.
但是请注意,将近似数字乘以精确数字并不会增加精度,上述输出中的有效位数可能表明了这一点。将这些数字四舍五入似乎更可取,但这将产生 384500 公里,这不是通常使用的数字 384400 公里。
更精确的平均值 semi-axis 是 384399 公里,大约 238855 英里,通常转换为 238900 英里。
四舍五入到指定数量的有效数字并不简单,C 库中没有标准函数可以做到这一点。您可以使用 snprintf
和 %.3e
来生成指数格式的数字,然后使用 strtod
转换回来,但是很麻烦且效率低下。