在C中翻转双/浮点符号的最快方法

时间:2011-03-06 20:55:51

标签: c floating-point double bit-manipulation sign

在C中翻转双(或浮点)符号的最快方法是什么?

我想,直接访问符号位是最快的方法,并找到以下内容:

double a = 5.0;
*(__int64*)&a |= 0x8000000000000000;
// a = -5.0

float b = 3.0;
*(int*)&b |= 0x80000000;
// b = -3.0

但是,上述内容不适用于负数:

double a = -5.0;
*(__int64*)&a |= 0x8000000000000000;
// a = -5.0

4 个答案:

答案 0 :(得分:40)

如果您只是在前置一个否定运算符,即-a,那么任何体面的编译器都会实现这种位操作。无论如何,你正在努力。你应该对它进行异或。这就是我测试它的编译器所做的事情(GCC,MSVC,CLang)。所以,请帮自己一个忙,写下-a

编辑:请注意C不强制执行任何特定的浮点格式,因此对非整数C变量的任何位操作最终都会导致错误的行为。


由于评论而编辑2 :这是GCC为x86_64发出的否定代码

.globl neg
    .type   neg, @function
neg:
.LFB4:
    .cfi_startproc
    pushq   %rbp
    .cfi_def_cfa_offset 16
    movq    %rsp, %rbp
    .cfi_offset 6, -16
    .cfi_def_cfa_register 6
    movss   %xmm0, -4(%rbp)
    movss   -4(%rbp), %xmm1
    movss   .LC0(%rip), %xmm0
    xorps   %xmm1, %xmm0  /* <----- Sign flip using XOR */
    leave
    .cfi_def_cfa 7, 8
    ret
    .cfi_endproc
.LFE4:
    .size   neg, .-neg

应该注意的是,xorps是针对浮点设计的XOR,可以处理特殊情况。这是SSE指令。

答案 1 :(得分:27)

a=-a

答案 2 :(得分:5)

此代码未定义,因为它违反了严格别名规则。 What is the strict aliasing rule? 为了做到这一点,你必须依靠编译器为你优化它。

答案 3 :(得分:3)

如果你想要可移植方式,只需乘以-1并让编译器优化它。