既然 float 不能表示所有的 int 那为什么在类型转换时 C++ 将 int 转换成 float?
问题
代码如下:
int i = 23;
float f = 3.14;
if (i == f) // 执行某段代码
编译器会将 i 转换成 float 类型,然后比较这两个 float 的大小,但是 float 能够表示所有的 int 吗?为什么没有将 int 和 float 转换成 double 类型进行比较呢?
回答
在整型数的演变中,当 int
变成 unsigned
时,会丢掉负数部分(有趣的是,这样的话, 0u < -1
就是对的了)。
和 C 语言中的大部分机制(在 C++中得到继承)一样,就硬件操作而言,常见的算术转换应该简明易懂。C 语言的发明者精通他们所使用机器上的汇编语言,他们编写的 C 语言对他们和像他们一样编写程序的人有直接的意义,直到使用汇编语言编写(诸如 UNIX 内核)的程序时。
现如今,一般来说,处理器并不具有混合类型的指令系统(如 float 和 double 相加、比较 int 和 float,诸如此类),因为如果这样做造成芯片晶圆的巨大浪费——如果你想支持更多不同的类型,你不得不实现更多的操作码。然而,在实际中,你只有实现"add int to int"、"compare float to float"和"multiply unsigned with unsigned"等功能的常见指令,这使得优先进行算术转换变得很有必要——它们是指令系统中两种类型的映射关系,它们中的大部分很有用处。
从习惯编写低级别机器代码的编程人员的角度来说,如果有了混合类型,那么在一般情况下最有可能使用的汇编指令就是那些只需要进行最少类型转换的指令。其中,有一种特殊情况就是浮点数的转换,特别是在 20 世纪 70 年代早期,当时 C 语言正在被开发,计算机运行速度很慢,而浮点数的计算是通过软件完成的,所以进行转换的成本很高。这拖慢了常用算术运算的转换开发——当时只有一种操作数实现了转换(这个例外就是 long 到 unsigned int 的转换,这种转换没有任何要求,在大部分机器上都可以进行。当然并不是全部,因为总有例外情况)。
所以,编写常用的算术转换是为了完成汇编程序员在大部分时间需要做的事情:即有两种不匹配的类型,将一种转换成另一种。这也就是汇编代码所做的事情,除非有特别原因需要进行其它类型转换。对于那些习惯编写汇编代码的人来说,除非是特殊需要,才会被迫去编写一种不同的类型转换。显然,这种情况下提出编写转换是很自然的事情。虽然,你可以简单地写成这样
if((double) i < (double) f)
顺便提一下,在这个问题中有趣的是, unsigned
的优先级高于 int
,所以把 int
和 unsigned
进行比较时,最终进行的是 unsigned 类型的比较(开头提到的 0u < -1
就是这个道理)。我猜测这可能是在早些时候(计算机发展初期),当时的人们认为 unsigned
比 int
在所表示的数值范围上受到的限制更小:现在还不需要符号位,所以可以使用额外的位来表示更大的数值范围。如果你觉得 int
可能会溢出,那么就使用 unsigned 好了——在使用 16 位表示的 ints 时这个担心会更明显。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论