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

hen*_*nes 10 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
Run Code Online (Sandbox Code Playgroud)

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

double a = -5.0;
*(__int64*)&a |= 0x8000000000000000;
// a = -5.0
Run Code Online (Sandbox Code Playgroud)

dat*_*olf 41

如果你只是在前置一个否定运算符,那么任何体面的编译器都会实现这种位操作-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
Run Code Online (Sandbox Code Playgroud)

应该注意的xorps是,XOR是为浮点设计的,可以处理特殊情况.这是一个SSE指令.

  • @inverse:你在说什么?在IEEE中,NaN编码时指数部分设置为全1,并且任何非零尾数(尾数零表示无穷大).符号位无关紧要.安静或信令(实际上)是尾数中的最高幅度位.再次,不是符号位. (6认同)

Dav*_*nan 28

a=-a

  • 这将是最有效的方式.浮点的位操作不可移植,永远不会通过按位运算符触摸浮点数.把它留给编译器. (13认同)

Mai*_*ter 5

此代码未定义,因为它违反了严格的别名规则. 什么是严格别名规则? 为了做到这一点,你必须依靠编译器为你优化它.