What is the fastest way to flip the sign of a double (or float) in C?
I thought, that accessing the sign bit directly would be the fastest way and found the following:
double a = 5.0;
*(__int64*)&a |= 0x8000000000000000;
// a = -5.0
float b = 3.0;
*(int*)&b |= 0x80000000;
// b = -3.0
However, the above does not work for negative numbers:
double a = -5.0;
*(__int64*)&a |= 0x8000000000000000;
// a = -5.0
Floats are faster than doubles when you don't need double's precision and you are memory-bandwidth bound and your hardware doesn't carry a penalty on floats. They conserve memory-bandwidth because they occupy half the space per number.
float is mostly used in graphic libraries for high processing power due to its small range. double is mostly used for calculations in programming to eliminate errors when decimal values are being rounded off.
Float and doubleDouble is more precise than float and can store 64 bits, double of the number of bits float can store. Double is more precise and for storing large numbers, we prefer double over float. For example, to store the annual salary of the CEO of a company, double will be a more accurate choice.
double has 2x more precision than float. float is a 32-bit IEEE 754 single precision Floating Point Number – 1 bit for the sign, 8 bits for the exponent, and 23* for the value. float has 7 decimal digits of precision.
Any decent compiler will implement this bit manipulation if you just prepend a negation operator, i.e. -a
. Anyway, you're OR-ing the bit. You should XOR it. This is what the compilers I tested it do anyway (GCC, MSVC, CLang). So just do yourself a favour and write -a
EDIT: Be aware that C doesn't enforce any specific floating point format, so any bit manipulations on non-integral C variables will eventually result in errornous behaviour.
EDIT 2 due to a comment: This is the negation code GCC emits for 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
It should be noted that xorps
is XOR designed for floatin points, taking care of special conditions. It's a SSE instruction.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With