Самый быстрый способ перевернуть знак double / float в C

каков самый быстрый способ перевернуть знак двойника (или поплавка) в 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 ответов


любой приличный компилятор реализует эту бит-манипуляцию, если вы просто добавляете оператор отрицания, т. е. -a. В любом случае, ты или ... Вы должны XOR это. Это то, что компиляторы, которые я тестировал, все равно делают (GCC, MSVC, CLang). Так что просто сделайте себе одолжение и писать -a

EDIT: имейте в виду, что 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.


a=-a


этот код не определен, поскольку он нарушает строгое правило сглаживания. что такое строгое правило антиалиасинга? Для этого вам придется полагаться на компилятор, оптимизирующий его для вас.


Если вы хотите портативный способ, просто умножьте на -1 и пусть компилятор оптимизирует его.