既然 float 不能表示所有的 int 那为什么在类型转换时 C++ 将 int 转换成 float?

发布于 2024-12-04 08:30:25 字数 1801 浏览 15 评论 0

问题

代码如下:

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 ,所以把 intunsigned 进行比较时,最终进行的是 unsigned 类型的比较(开头提到的 0u < -1 就是这个道理)。我猜测这可能是在早些时候(计算机发展初期),当时的人们认为 unsignedint 在所表示的数值范围上受到的限制更小:现在还不需要符号位,所以可以使用额外的位来表示更大的数值范围。如果你觉得 int 可能会溢出,那么就使用 unsigned 好了——在使用 16 位表示的 ints 时这个担心会更明显。

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据

关于作者

唯憾梦倾城

暂无简介

文章
评论
26 人气
更多

推荐作者

櫻之舞

文章 0 评论 0

弥枳

文章 0 评论 0

m2429

文章 0 评论 0

野却迷人

文章 0 评论 0

我怀念的。

文章 0 评论 0

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文