问题
I am getting OverflowException's thrown at me when I don't want them (or so I think). I am performing some odd calculations where I expect the values to overflow, discarding overflowed bits. It seems I can't get this to work properly though. Basically this is one pair of i and j which happens as I iterate over huge sets (int.MinValue to int.MaxValue).
// i and j are ints
// i is -2147483648
// j is -1
var x = i / j;
// I also tried using unchecked keyword, but it doesn't help
var x = unchecked(i / j);
Update:
The expected mathematic value of -2147483648 / -1 is 2147483648. However, this certain code doesn't really attempt to find the number. This is part of a series of bit manipulation things gone a bit hard to understand. To be honest, I don't even know myself what the intention was because I didn't really document the method, and all it took was one day away from it to raise serious WTF-bubbles over my head. All I know it works as intended with special code designed to handle the case.
About the expected value:
Since int can only hold 2147483647 at it's max, I expect to discard the overflow yielding value 0.
If I've learned anything about this at all, it's probably the importance of documentation for obscure methods.
回答1:
I believe this is the only case in which you'll get this exception. It's the only division within the Int32
range which can overflow. (There's division by zero of course, but that's a different exception.)
So if you want to avoid OverflowException
you only need to deal with this case. What do you want it to do? Write a method which spots this exact case, and otherwise does normal division.
Note: this is also why you shouldn't try to reverse a comparison by just negating the result. If you want to sort something in descending order instead of ascending, then instead of using -Compare(x, y)
use Compare(y, x)
. The negation doesn't give overflow for int.MinValue
(unless you're in a checked context) - it just silently returns int.MinValue
.
回答2:
Twos complement means that integers will range from 2^32 - 1 to -2^32, so -2147483648 / -1 is returning a number which can't be represented by an int
.
You could try putting it into a long
. There's no reason to use a var
in this situation.
回答3:
You can workaround this with a bit of casting to/from Int64
:
var x = (int)((long)i / j);
回答4:
You do this. Why would you use var
here? It loses the ability to show you the type of arithmetic result all for saving 1 character...
long x = (long)i / j;
If you want saturation, you can:
int x = (int)Math.Min((long)i / j, int.MaxValue);
来源:https://stackoverflow.com/questions/1300777/how-can-i-stop-overflowexception-being-thrown-on-integer-division