我对隐式类型转换有点困惑。鉴于以下程序
float x = 4.23423451;
double y = 4.23423451;
float z = 101.9876;
float res1 = x * z;
float res2 = y * z;
std::cout << "res1 & res2 " << res1 << " & " << res2 << std::endl;
std::cout << "equality " << (res1 == res2) << std::endl;
输出是
res1 & res2 431.839 & 431.839
equality 1
我的问题是“对于 x、y 和 z (x = y) 的任何值以及任何编译器来说,等式总是成立吗?”
In
res2 = y * z;
变量“y”是否会被类型转换为 float,或者变量“z”是否会被类型转换为 double?
See 我的评论 https://stackoverflow.com/questions/12396132/c-implicit-type-conversion#comment16656609_12396132.
这是明确定义的。中间表达式为z
将扩大到double
, so y * z
将是一个double
表达。然后隐式缩小转换会将其转换为float
用于存储在res2
。同样的缩小范围适用于res1
.
这反映在§5¶9 表达式 [expr]C++11 标准。
许多期望算术或枚举类型操作数的二元运算符会以类似的方式导致转换并产生结果类型。目的是产生一个通用类型,这也是结果的类型。这种模式称为常见的算术转换,其定义如下:
...
- 否则,如果任一操作数是
double
,另一个应转换为double
.
- 否则,如果任一操作数是
float
,另一个应转换为float
.
...
然而,这并不能确保平等成立。
话虽如此,res1
不一定等于res2
——这很大程度上取决于精度float
and double
在环境中。这两个文字甚至可能不相等——4.23423451f
甚至不需要等同于4.23423451
。你不能确定static_cast<double>(static_cast<float>(4.23423451))
将等于4.23423451
.
See §5.17¶3 赋值和复合赋值运算符 [expr.ass].
如果左操作数不是类类型,则表达式将隐式转换(第 4 条)为左操作数的 cv 非限定类型。
§4 标准转换 [conv]规定如下:
标准转换是具有内置含义的隐式转换。第 4 条列举了完整的此类转换集。 A标准转换顺序是按以下顺序排列的标准转换序列:
...
- 以下集合中的零个或一个转换:整数提升、浮点提升、整数转换、浮点转换、浮点整数转换、指针转换、指向成员的指针转换和布尔转换。
正如在§4.6 浮点提升 [conv.fpprom],
- 类型的纯右值
float
可以转换为类型的纯右值double
。该值不变。
- 这种转换称为浮点提升.
... and §4.8 浮点转换 [conv.double],
-
浮点类型的纯右值可以转换为另一种浮点类型的纯右值。如果源值可以在目标类型中精确表示,则转换的结果就是该精确表示。如果源值位于两个相邻的目标值之间,则转换的结果是实现定义的对其中任一值的选择。否则,行为是未定义的。
-
允许作为浮点提升的转换不包括在浮点转换集中。
这里的问题是,我们有多种情况下我们的转换不正确晋升,而是缩小到可能较低精度的类型(double
to float
).
本质上,任何时候您转换double
to float
,您可能会失去精度。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)