C++ 为什么C++;当浮点不能表示所有的int值时,是否将int提升为float?

C++ 为什么C++;当浮点不能表示所有的int值时,是否将int提升为float?,c++,types,int,floating-point-conversion,promotions,C++,Types,Int,Floating Point Conversion,Promotions,假设我有以下几点: int i = 23; float f = 3.14; if (i == f) // do something i将被提升为float并比较两个float数字,但是float是否可以表示所有int值?为什么不将int和float都升级为double IEE754可以将所有整数精确地表示为浮点数,最多约为223,如本文所述 问题2:为什么不将int和float都提升为double 标准中关于这些转换的规则是对K&R中的规则的轻微修改:这些修改适应了添加的类型和保留值的规则添加

假设我有以下几点:

int i = 23;
float f = 3.14;
if (i == f) // do something

i
将被提升为
float
并比较两个
float
数字,但是
float
是否可以表示所有
int
值?为什么不将
int
float
都升级为
double

IEE754可以将所有整数精确地表示为浮点数,最多约为223,如本文所述

问题2:为什么不将int和float都提升为double

标准中关于这些转换的规则是对K&R中的规则的轻微修改:这些修改适应了添加的类型和保留值的规则添加了Explicit许可证,以执行比绝对必要的“更宽”类型的计算,因为这有时会生成更小、更快的代码,更不用说更经常的正确答案了。只要获得相同的最终结果,也可以按“假设规则”以“更窄”类型执行计算。显式转换始终可以用于获得所需类型的值

在更广泛的类型中执行计算意味着给定的
float f1和<代码>浮动f2
f1+f2
可能以
双精度计算。这意味着给定的
inti
浮点f
i==f
可能以
double
精度计算。但是,正如hvd在注释中所述,不需要以双精度计算
i==f

C标准也这么说。这些被称为通常的算术转换。以下描述直接取自ANSI C标准

…如果任一操作数具有类型浮点,则另一个操作数将转换为类型浮点

你也可以在照片上看到

这是一个相关的链接。一个更具分析性的来源是

下面是另一种解释方法:通常的算术转换是隐式执行的,以将其值转换为公共类型。编译器首先执行整数提升,如果操作数仍然具有不同的类型,则将它们转换为以下层次结构中显示最高的类型:


.

根据
int
包含多少位,即使
double
也可能无法表示所有
int

为什么不将int和float同时升级为double?

可能是因为将两种类型转换为
double
比使用其中一个操作数成本更高,后者已经是
float
,如
float
。它还将为与算术运算符规则不兼容的比较运算符引入特殊规则


也无法保证浮点类型将如何表示,因此假设将
int
转换为
double
(甚至
long double
)进行比较将解决任何问题,这将是一种盲目的想法。

类型提升规则设计得非常简单,并且能够以可预测的方式工作。C/C++中的类型自然地按照它们可以表示的类型进行“排序”。有关详细信息,请参阅。虽然浮点类型不能表示整数类型所表示的所有整数,因为它们不能表示相同数量的有效位数,但它们可能能够表示更大的范围

为了具有可预测的行为,当需要类型升级时,数值类型始终转换为范围较大的类型,以避免较小范围内的溢出。想象一下:

int i = 23464364; // more digits than float can represent!
float f = 123.4212E36f; // larger range than int can represent!
if (i == f) { /* do something */ }
如果对整型进行转换,则当转换为int时,float
f
肯定会溢出,从而导致未定义的行为。另一方面,将
i
转换为
f
只会导致精度损失,这是不相关的,因为
f
具有相同的精度,因此比较仍然可能成功。此时由程序员根据应用程序需求解释比较结果


最后,除了双精度浮点数在表示整数时遇到相同的问题(有效位数的数量有限)之外,在这两种类型上使用提升将导致
i
具有更高的精度表示,而
f
注定具有原始精度,因此,如果开始时
i
的有效位数大于
f
,则比较不会成功。现在这也是未定义的行为:对某些夫妇(
i
f
)来说,比较可能成功,但对其他夫妇则不成功。

当创建一种编程语言时,一些决策是凭直觉做出的

例如,为什么不将int+float转换为int+int,而不是float+float或double+double?为什么要调用int->float提升,如果它包含相同的位数?为什么不把float->int称为提升

如果您依赖隐式类型转换,您应该知道它们是如何工作的,否则只需手动转换即可

有些语言完全可以在没有任何自动类型转换的情况下进行设计。在设计阶段,并不是每一个决策都有合理的理由


带有duck类型的JavaScript在幕后有着更加模糊的决策。设计一种绝对合乎逻辑的语言是不可能的,我认为它符合哥德尔不完全性定理。你必须平衡逻辑、直觉、实践和理想。

当积分升级中
int
升级为
unsigned
时,负值也会丢失(这会导致
0u<-1
为真等乐趣)

与C语言中的大多数机制(在C++中继承)一样,通常的算术转换应该从硬件操作的角度来理解。C的制造商非常熟悉这个组件
if((double) i < (double) f)
int x(float a)
{ ... }
int y(a)
float a;
{ ... }