Reputation: 103
It's easy to get C# to throw an exception on an integer overflow. However, that's not what I'm looking for. I want to detect the overflow so I can continue the calculation in the high order. I'm building a sort of big int implementation.
I could catch the overflow exception, but that's not great for performance. Not to mention that it's conceptually incorrect.
Any idea how to check for overflow without exceptions?
Upvotes: 1
Views: 1667
Reputation: 205649
If you are seeking for a carry behavior, other answers/comments cover that pretty well. However, I find the original question to be an interesting brain puzzle (although not practically useful), specifically what is the best performance pure C# way to detect 2 signed integers add overflow. Ideally it would generate a minimum IL instructions with no branches. Here is the best I ended up - one with bool flag (true when overflow, false otherwise) and another with int "bit" (1 when overflow, 0 otherwise). Both satisfy the above criteria, "bit" version has few less IL instructions. Enjoy:-)
static int Add(int a, int b, out bool overflowFlag)
{
unchecked
{
int c = a + b;
overflowFlag = ((a ^ b) >= 0) & ((a ^ c) < 0);
return c;
}
}
static int Add(int a, int b, out int overflowBit)
{
unchecked
{
int c = a + b;
overflowBit = (int)((uint)((a ^ c) & ~(a ^ b)) >> 31);
return c;
}
}
Upvotes: 5
Reputation: 2603
If you want to implement addition and subtraction with carry, I really recommend using uint
instead of int
! Cast both values to ulong
before doing the calculation:
//Adds a and b
uint[] a = ... , b = ... ;//input
ulong carry=0
for(int i=0;i<length;i++)
{
carry += (ulong)a[i] + (ulong)b[i];
uint result = (uint)carry;
carry >>= 32;//divide by 2^32
//TODO: store result
}
//TODO: process remaining carry
I had problems with sign extension, when i first implemnted something like this, hence the unsigned types everywhere.
Upvotes: 1