C 中从 Float 到 Int 的类型转换导致数字大不相同,为啥?
Posted
技术标签:
【中文标题】C 中从 Float 到 Int 的类型转换导致数字大不相同,为啥?【英文标题】:Type-Casting in C from Float to Int results in wildly different number, why?C 中从 Float 到 Int 的类型转换导致数字大不相同,为什么? 【发布时间】:2020-07-27 20:05:49 【问题描述】:输入:
#include <stdio.h>
#include <math.h>
int main(void)
printf("%i", (int)pow(10,10));
return 0;
输出:
-2147483648
由于某种原因,pow()
在我运行它时会产生 double
而不是 int
(我使用的是 Pow()
,因为由于某种原因,指数没有编码到 C 中)。有什么原因吗?
【问题讨论】:
你知道int
可以存储的最大数量是多少吗?
你的目标是什么?您可以在 printf 中使用 .0 格式而不是强制转换吗?
【参考方案1】:
对(int)pow(...)
的强制转换是将double
值转换为整数类型。 double
是 C 中可用的真正浮点类型之一。
关于将浮点类型转换为整数的规则可以在in C11 draft 6.3.1.4p4 找到,但是cppreference real floatinf-integer conversion 上有更简单的版本:
任何实浮点类型的有限值都可以隐式转换 到任何整数类型。除非上面的布尔转换涵盖, 规则是:
如果结果值可以由目标类型表示,则使用该值 否则,行为未定义The fractional part is discarded (truncated towards zero).
假设您有一个健全的平台,您的 sizeof(int)
是 4 和 INT_MAX=2147483647
。 pow(10, 10)
的结果是 (double)10000000000.0
,它的小数部分无法在目标整数类型 (int)
中表示。你的代码行为就是undefined。
【讨论】:
【参考方案2】:4 字节整数可以容纳的最大值范围为 -2,147,483,648 到 2,147,483,647。 10^10 的结果是 10,000,000,000,超出了限制,转换溢出,产生了意想不到的结果。就是这样。
【讨论】:
and the integer overflows
呈现的代码中没有溢出。
@Rohan Bari 谢谢!我完全忘记了对变量的大小限制
不,没有“溢出”。 “溢出”是什么操作?在什么意义上?
@KamilCuk:10,000,000,000 到int
的转换溢出。 C 标准没有为“溢出”定义专门的 C 含义,因此这只是指不适合目标格式的结果的普通用法。 C 2018 6.3.1.4 1 讨论了浮点到整数的转换,并说“如果整数部分的值不能用整数类型表示,则行为未定义。”
@RohanBari:转换的行为不是由 C 标准定义的,但我们观察到的结果 -2,147,483,648 也不是“意外的”。虽然我们不能依赖它,因为没有一些规范说这将是结果,但这是一个常见的、并不令人惊讶或完全出乎意料的结果。例如,英特尔指令通常会为浮点到整数的转换生成这个。以上是关于C 中从 Float 到 Int 的类型转换导致数字大不相同,为啥?的主要内容,如果未能解决你的问题,请参考以下文章