对两个双精度变量进行异或操作

4
我写了以下两行代码:
第一行代码:
int a;
a=a^a;

第二行:

double d;
d=d^d;

第一行没问题,但是第二行却出错了:

error: invalid operands of types ‘double’ and ‘double’ to binary ‘operator^’

有人可以告诉我位运算的XOR运算符为什么适用于两个int变量但不适用于两个double变量吗?

看起来很傻,但是我的程序没有这个运算符真的无法运行!


2
两个IEEE 754双精度数进行异或(XOR)操作的确切目的是什么? - Frédéric Hamidi
我正在制作一个哈希算法...我想要对两个64位变量进行异或运算....所以我尝试使用double类型.... - Rohith R
2
你应该使用64位整数uint64_t或long long,double在这种情况下没有意义。 - chrmue
嗯...你给了@chrmue非常有用的想法,非常感谢。 - Rohith R
1
@FrédéricHamidi,这将允许在不声明临时变量的情况下进行内存值交换。 - Francisco Chavez-Tejeda
3个回答

4

因为标准规定。

C++11 §5.12 按位异或运算符

执行通常的算术转换;结果是操作数的按位异或函数。 该运算符仅适用于整数或枚举操作数。

在我看来,对两个double进行异或操作没有多少意义。


我认为“标准如此规定”并不是一个很好的理由,它并不能解释为什么事情是这样的。 - Jack Aidley
1
double值上使用XOR有一些合法的用途。例如,如果您知道s确切地是+1或-1,并且您需要计算s*a,并且您具有标准IEEE 754值的布局,则s^as*a产生相同的结果,但在大多数CPU上具有更低的延迟。此外,std::copysign()通常使用XOR实现。英特尔添加了像XORPS和XORPD这样的指令到它们的SSE(2)指令集中是有原因的。 - Kai Petzke

2

我认为其他答案已经很好地解释了为什么默认情况下不支持它。你可能不应该这样做,但是以下是如何实现的方法:

    double d = 12345.6789;
    unsigned long long* uPtr = (unsigned long long*)&d;
    unsigned long long uXor = (*uPtr) ^ (*uPtr);
    double dXor = *((double*)&uXor);


1
因为XOR和其他布尔位运算符是针对二进制操作定义的,例如0b10^0b01 = 0b11,但这对于表示不同于值的任何内容都没有意义。如果你XOR 4.01.0,你应该得到值的XOR,即5.0,还是表示的按位XOR?如果是前者,那么对于精度不完全重叠的值,例如'1.89e92and0.01',该怎么办呢?而后者甚至很难定义(并且可能没有意义),因为C++标准没有精确定义double的表示方式,在计算和存储过程中可能会有不同的表示方式。

我找不到为什么在按位异或两个相同大小的变量时,IEEE格式必须介入...它所要做的就是取两个变量的对应位,进行异或运算,然后将结果放回...问题出在哪里呢.....? - Rohith R
这个理由有点靠不住。即使C++标准没有强制要求使用二进制补码,你也可以对有符号整数执行异或操作。每个变量都有一个位表示,无论其“精度”如何。 - pezcode
1
@PRP:问题是“这是什么意思?” - 你可以对存储的表示进行位运算,但它没有任何意义,也没有任何保证一致的行为,所以为什么要允许呢?更重要的是,你可以通过简单地进行几次类型转换来轻松实现。 - Jack Aidley
1
@PRP:这个IEEE格式是从哪里来的?C++并没有强制要求使用它。它也可以将您的浮点数存储在三进制中。 - PlasmaHH
单个按位异或操作在浮点数类型上执行时可能没有合理的价值,但复合按位异或操作确实有价值。通过三个异或操作,您可以交换相同类型的两个变量的内存值,只要这两个变量不驻留在同一内存位置。如果按位异或适用于双精度浮点数,则类似void Switch(ref double x,ref double y)的内容将无需声明临时变量。 - Francisco Chavez-Tejeda

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接