Code example:
float f = 123.456;
int i = 12345;
// negate by changing sign
i = -i;
f = -f;
// negate by multiplying with -1
i *= -1;
f *= -1.0f;
Apart from aesthetics, is there any factual reason why one should prefer one way over the other?
To me multiplication seems a little unnecessary. But I see the multiplication style more often, and wanted to hear if there's a good reason for it, besides preference.
n&1 performing a binary AND between n and 1. if (n&1) is checking for whether a number is odd, since odd numbers will have LSB of 1 and even numbers don't.
| is bitwise OR operation. |= just assigns the bitwise OR of a variable with another to the one on the LHS.
Less than or equal to.
The &= operator concatenates the String expression on its right to the String variable or property on its left, and assigns the result to the variable or property on its left.
Based on my answer to “fastest-way-to-negate-a-number”
The answers to a similar question have indicated that:
a = -a
, a *= -1
etc.
= -a
and 3 for *= -1
.There is however a practical advantage to the *= -1
idiom: you only have to write the left hand side once, and it is only evaluated once. This is relevant when the LHS is long, complex or expensive or may have side-effects:
(valid ? a : b)[prime_after(i++)] *= -1;
*look_up (input) *= -1; // Where look_up may have side-effects
parity[state][(unsigned int)getc(stdin)] *= -1;
variable_with_a_long_explanatory_name *= -1;
A further advantage of this irredundancy is that when seeking a bug one can be certain that the number really is being negated in situ, and that there is no subtle difference in the two expressions.
Once one has adopted an idiom, one tends to stick with it in other situations, so it is understandable to stick to *= -1
.
Recommend to use what explains the code best, unless one is working with an old platform or compiler. In that case, use negation.
Following are some obscure differences:
int
format with non-2's complement:
In days of yore, a multiplication by of 0
and -1
could result in 0
yet a negation of 0
could result in -0
. Of course 0
and -0
have the same value, yet different signs. Not all non-2's complement machines worked the same concerning this.
Floating Point:
Speed: A smart compiler will create efficient and likely the same code for f *= -1.0f
and f *= -f
. Yet a lesser compiler may not identify this equivalence and perform one slower than the other.
Rounding: A negation need not invoke any rounding, yet a multiplication, even by 1.0, can involve a round. This happens in 2 cases: when the variables are of a higher precision (allowed in modern C, FLT_EVAL_METHOD
) and in machines (more like relics) that performed their FP using base-16 rather than base-2. In this latter case, the precision wobbles (e.g IBM Floating Point) and a simple multiplication would present a rounded product. This behavior is uncommon these days.
There also exist FP formats that have multiple representations for the same value, but a multiplication by 1 would return the preferred format, whereas negation would simply flip the sign bit. The results are the same value, but different bit patterns of the FP number.
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