假设我有以下内容:
int i = 23;
float f = 3.14;
if (i == f) // do something
i
将被提升为浮点数
并且将比较两个浮点数
数字,但是浮点数
可以表示所有int
值吗?为什么不将int
和浮点数
提升为双
?
类型提升规则旨在简单并以可预测的方式工作。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时,浮点f
肯定会溢出,导致未定义的行为。另一方面,将i
转换为f
只会导致精度损失,这是无关紧要的,因为f
具有相同的精度,因此比较仍然有可能成功。此时由程序员根据应用程序要求解释比较的结果。
最后,除了双精度浮点数在表示整数时遇到相同的问题(有效位数的数量有限)之外,对这两种类型使用提升将导致i的表示精度更高,而f的表示精度注定要达到原始精度,因此,如果开始时i的有效位数大于f,则比较将不会成功。现在,这也是一种未定义的行为:对一些夫妇来说,这种比较可能会成功(i
,f
),但对其他夫妇来说则不会成功。
根据int包含多少位,即使是double也可能无法表示所有int值。
为什么不将int和浮动都提升为双精度?
可能是因为将这两种类型转换为double比使用其中一个操作数的成本更高,后者已经是float,就像float一样。它还将为与算术运算符规则不兼容的比较运算符引入特殊规则。
也不能保证浮点类型将如何表示,因此假设将int
转换为Double
(甚至long Double
)进行比较将解决任何问题。
在积分升级中,当int升级为unsigned时,负值也会丢失(这会导致类似于0u的乐趣
与C中的大多数机制(在C中继承)一样,通常的算术转换应该从硬件操作的角度来理解。C语言的制造者非常熟悉他们所使用的机器的汇编语言,他们编写C语言是为了在编写之前都是用汇编语言编写的东西(如UNIX内核)时,让自己和喜欢自己的人能够立即理解。
现在,处理器通常不具有混合类型的指令(将float添加到double,将int与float进行比较,等等),因为这将是对晶圆上不动产的巨大浪费——您必须实现想要支持不同类型的任意多倍的操作码。由于只有“将int添加到int”、“将float与float进行比较”、“无符号与无符号相乘”等指令,因此首先需要进行常规的算术转换——它们是两种类型到指令族的映射,最适合与它们一起使用。
从习惯于编写低级机器代码的人的角度来看,如果您有混合类型,那么在一般情况下,您最可能考虑的汇编指令是那些需要最少转换的指令。浮点运算的情况尤其如此,因为转换在运行时非常昂贵,尤其是在20世纪70年代早期,当C语言被开发出来时,计算机速度很慢,浮点运算是在软件中完成的。这表明在通常的算术转换中,只有一个操作数被转换(唯一的例外是长的无符号整数,其中长的无符号整数可以转换为无符号长的,这在大多数机器上不需要做任何事情。在任何例外情况下,可能都不需要做)。
因此,编写通常的算术转换是为了完成汇编代码编写人员在大多数情况下会做的事情:您有两种不适合的类型,将一种转换为另一种,这样就可以了。这就是你在汇编代码中要做的,除非你有特殊的理由去做,对于那些习惯于编写汇编代码并且有特殊的理由去强制进行不同的转换的人来说,明确地要求转换是自然的。毕竟,你可以简单地写
if((double) i < (double) f)
顺便提一下,在本文中值得注意的是,层次结构中无符号比int更高,因此将int与无符号进行比较将以无符号比较结束(因此
但如果将浮点数或整数减小或增大一定量,则比较运行得快得多: 更改比较运算符(例如,改用或)不会以任何明显的方式影响时间。 这不仅仅与幅度有关,因为选择较大或较小的值会导致更快的比较,所以我怀疑这是由于位排列的某种不幸方式造成的。
问题内容: 我有一个JSON字符串,其中包含一些具有以下值的密钥:123.00。当我使用json_decode函数时,我得到的解码字符串的前一个键等于123,而不是123.00。有没有一种方法可以正确解码这些值而不用引号引起来? 问题答案: 目前,这是作为PHP错误引起的: 错误报告 :https : //bugs.php.net/bug.php? id =50224 将来,可能会存在通过参数传递
问题内容: 我想知道为什么在计算表达式或按位运算时将和提升为值的原因? 问题答案: 因为Java语言规范是这样说的。第5.6.1节定义了用于撤消某些运算符的一元数值提升,并指出: 如果操作数的编译时类型为byte,short或char,则通过扩展基元转换(第5.1.2节)将其提升为int类型的值。 关于二进制数值运算符(“ binary”表示具有两个操作数,如“ +”的运算符)的评估的第5.6.2
所以浮点运算是不精确的,但这并不能完全解释这里发生的事情:
我试图检查一个数字是否是一个完美的平方。然而,我正在处理非常大的数字,所以python认为它的无穷大出于某种原因。有办法绕过这个吗?这是代码,第一个变量只包含一堆非常非常非常非常大的数字
我正在用python研究基本微积分和阶乘。试图从牛顿级数生成PI,但我不能超过171次迭代,因为这个错误:overflowerrror:int太大,无法转换为float。代码如下: 我导入了这个:从数学导入阶乘,gamma/从数学导入sqrt