Самый быстрый способ перевернуть знак двойного / плавающего в C - PullRequest
10 голосов
/ 06 марта 2011

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

41 голосов
/ 06 марта 2011

Любой приличный компилятор будет реализовывать эту битовую манипуляцию, если вы просто добавите оператор отрицания, то есть -a.Во всяком случае, вы или немного.Вы должны 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.

28 голосов
/ 07 марта 2011

a=-a

5 голосов
/ 07 марта 2011

Этот код не определен, так как он нарушает строгое правило псевдонимов. Что такое строгое правило псевдонимов? Чтобы сделать это четко определенным, вам придется положиться на оптимизатор, который его оптимизирует для вас.

3 голосов
/ 06 марта 2011

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...