48

In C# I see that

-1 * int.MinValue == int.MinValue

Is this a bug? It really screwed me up when I was trying to implement a search tree. I ended up using (int.MinValue + 1) so that I could properly negate it.

jjnguy
  • 136,852
  • 53
  • 295
  • 323
James
  • 1,085
  • 9
  • 16

5 Answers5

60

This is not a bug.

int.MinValue * -1 is 1 greater than int.MaxValue can hold. Thus, the number wraps around back to int.MinValue.

This is basically caused by an integer overflow.

Int32.MinValue:

The value of this constant is -2,147,483,648

Int32.MaxValue:

The value of this constant is 2,147,483,647

So, -2,147,483,648 * -1 = 2,147,483,648 which is 1 greater than Int32.MaxValue.

jjnguy
  • 136,852
  • 53
  • 295
  • 323
  • 1
    integer math is sooo coool! ;) – Mark Schultheiss Sep 02 '10 at 19:08
  • 1
    @Mark, in this case, I think it is not cool. It is confusing. – jjnguy Sep 02 '10 at 19:29
  • Depends how you look at it. From a bitwise perspective with `-x := ~x + 1` and `Int32.MinValue` being `1000 0000 0000 0000 0000 0000 0000 0000` it's actually quite plausible. And the '32' in `Int32` does point just right to that direction :) – back2dos Jan 30 '11 at 12:44
9

It's not a bug, it's an overflow.

In two's complement representation, the space of representable numbers is not symmetric. The opposite of the smallest integer cannot be represented. Computing it overflows and gives you the same number again.

Pascal Cuoq
  • 79,187
  • 7
  • 161
  • 281
8
int i = -1 * int.MinValue;

This doesn't even compile unless you disable checking:

error CS0220: The operation overflows at compile time in checked mode
Darin Dimitrov
  • 1,023,142
  • 271
  • 3,287
  • 2,928
  • Just wanted to note that checked mode is apparently disabled by default.http://msdn.microsoft.com/en-us/library/h25wtyxf.aspx – Aelphaeis Jul 31 '14 at 13:59
2

No, it isn't a bug. It is the nature of twos complement integer arithmetic.

For example, let us take a signed byte value which goes between -128 and 127.

127(0x7f)+1 = 128(0x80). However, 0x80 is in fact the binary representation of -128.

Thus, for a byte, 128(0x80) = -128(0x80)

So -128(0x80) * -1 = 128(0x80) = -128(0x80)

Torlack
  • 4,395
  • 1
  • 23
  • 24
2

Put a checked region on it and see the "bug" evolve into an exception. Or try VB.NET (which as far as I recall is checked by default unlike C#).

Andrei Rînea
  • 20,288
  • 17
  • 117
  • 166