Inverting [or rather: negating] a number: what's quickest?

Suppose that I want invert a number, i.e. 5 becomes -5 or -10 becomes 10. Mathematically, I can either multiply it by -1 or subtract it from 0. But what is quickest/most efficient on an 8-bit AVR? Or is the compiler smart enough to optimize either style to the fewest instructions?

// Style #1
int one (const int number)
   return number * -1;

// Style #2
int two (const int number)
    return 0 - number;

Is there any difference if I work on a float instead of an int?

floats are slower, and require more flash if the math library has to be used.

In my code, I usually use
result = 0 - theNumber;

That's not "inverting", it's "negating".

Inverting usually means dividing one by the number, 1/x.

For negating, you can use unary negation:

return -number;

If you are worried about performance, don't create a function for this, that might introduce some overheads (although the compiler's optimiser might find ways to remove those).

Yes, you're right. Mathematical jargon has never been my cup of tea (which is why I provided an example, just to be sure). For some reason, I tend to think of negating in boolean context only, go figure.

Creating a function just for that in real code would be silly indeed, but that line was part of a larger function and I just singled it out to make things shorter. I'm aware of unary -, but is it better emulated by style #1 or style #2 if I just happen to use one or the other?

Afterthought: Curiously enough, when we talk about a display, inverting it means making black white and making white black, doesn't it? Yet, what we are really doing is negating each pixel's value.

I might use that, but I usually include the 0, so it stands out in code… it will be optimised away anyway, but makes the intent clearer. To me anyway !

+1 for clarity. That little minus sign before a name is hard to see at a glance.

for simplicity and readability I'd go for
a = -a;
as a signed integer.

For speed, I wonder if the bitwise xor instruction is faster (but much less comprehensible)
int nx = 0xFFFF;
int a = 12;
a = a ^ nx; //invert all bits to form 1's complement
a++; //add 1 to form 2's complement


Still another style. Maybe, at the end of the day, the compiler will just optimize everything into that?

Exactly the same speed, I would guess. Addition, subtraction, bitwise and/or/xor and single-bit shifts are probably all one cycle operations, even for the relatively simple ALU in an AVR chip. Multiplication, division, and, I guess, multiple-bit shifts will be done in software or at least as multiple cycle operations in AVR chips.

So this seems to imply that number * -1 is slower than 0 - number, since multiplication is involved in the first case. Unless the compiler treats multiplication by -1 as a subtraction in disguise and optimizes it away.

You are correct, in theory. AVR chips used in most Arduino don't have hardware supported multiplication I think, and almost certainly not division, and definitely not floating point operations of any sort. Even more sophisticated chips, that can do such things in hardware, can't do then in a single cycle, so multiplying by -1 will always be slower than subtracting from 0 on almost any chip, I suspect. But, in practice, as you suspect, it may be that the compiler can spot and optimise stuff like that and do it in a more efficient way so that it makes no difference.

Guess what? Apparently the atmega328 used in most Arduinos does have hardware multiplication support!

● Advanced RISC architecture
● 131 powerful instructions – most single clock cycle execution
● 32  8 general purpose working registers
● Fully static operation
● Up to 16MIPS throughput at 16MHz
On-chip 2-cycle multiplier

But as I suspected, it takes 2 cycles, where subtraction will only take one cycle.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.