14

Cでdouble(またはfloat)の符号を反転する最速の方法は何ですか?

符号ビットに直接アクセスするのが最速の方法であると考えたところ、次のことがわかりました。

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

4 に答える 4

44

否定演算子を前に付けるだけで、適切なコンパイラはこのビット操作を実装します-a。とにかく、あなたはビットをORしている。XORする必要があります。これは、私がテストしたコンパイラー(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命令です。

于 2011-03-06T20:59:39.120 に答える
34

a=-a

于 2011-03-06T21:00:53.113 に答える
5

このコードは、厳密なエイリアシングルールに違反しているため、未定義です。 厳密なエイリアシングルールとは何ですか? これを明確に定義するには、コンパイラが最適化することに依存する必要があります。

于 2011-03-06T21:01:26.060 に答える
4

移植可能な方法が必要な場合は、乗算し-1てコンパイラに最適化させてください。

于 2011-03-06T20:58:03.803 に答える