对于像有符号整数、浮点数和双精度等类型,是否有一种明确的操作可以快速实现翻转一个比特位?因为如果我记得正确(这是一个非常大的如果),这只是一件轻而易举的事情,我想知道是否有一个显式的操作可以使代码运行更快?
编辑:好的,仅针对浮点类型,我忘记使用我的脑子了,请原谅。
对于像有符号整数、浮点数和双精度等类型,是否有一种明确的操作可以快速实现翻转一个比特位?因为如果我记得正确(这是一个非常大的如果),这只是一件轻而易举的事情,我想知道是否有一个显式的操作可以使代码运行更快?
编辑:好的,仅针对浮点类型,我忘记使用我的脑子了,请原谅。
-a
和a * -1
是不同的操作。1 C++标准中没有明确要求实现在这两者之间产生不同的结果,因此编译器可以将它们视为相同的。C++标准也没有要求实现将它们视为相同的,所以编译器可以将它们视为不同的。
C++标准在指定浮点运算方面非常宽松。C++实现可能认为一元的-
是数学运算,使得-a
等同于0-a
。另一方面,C++实现也可能将一元的-
视为IEEE-754 negate(x)操作,根据IEEE 754-2008 5.5.1:
… negate(x)将一个浮点操作数x复制到一个目标中,该目标与源具有相同的格式,在复制时翻转符号位。 negate(x)不同于subtraction(0, x)…
它们的区别包括:
因此,你可能会发现编译器会生成一个XOR指令来执行a = -a;
,只是翻转了符号位,但是会为a *= -1;
生成一个乘法指令。如果实现不支持浮点标志、陷阱、信号NaN或其他使取反和减法/乘法可区分的内容,它应该只为a *= -1;
生成一个XOR指令。
Godbolt显示x86-64 Clang 11.0.0使用默认选项为-a
使用xor
,为a * -1
使用mulss
。但是x86-64 GCC 10.2为两者都使用xorps
。
1 我在这里仅隔离了-
和*
操作;赋值部分不是我们关注的内容。
2 “Signal” 在这里是按照 IEEE-754 规范使用的术语,表示发生了异常情况并给出了相应的指示。这可能会导致标志被触发,还可能会引起影响程序控制的陷阱。它不同于 C++ 信号,尽管陷阱可能会导致 C++ 信号。