views:

1518

answers:

6

I want alwaysPositive to be assigned a positive number with all possible values for lareValue1 and largeValue2 (these are at least 1).

The following statement causes a buffer overflow:

int alwaysPositive = (largeValue1 + largeValue2) / 2;

I know I can prevent it by substracting and adding:

int alwaysPositive = largeValue1 + ((largeValue2 - largeValue1) / 2);

But in other programming languages I can use an unsigned bitshift to do the trick:

int alwaysPositive3 = (largeValue1 + largeValue2) >>> 1;

How can I do this in C#?


The answers below all solve the problem. There are probably lots of ways to do this, but they all (including my solutions) have one thing in common: they all look obfuscated.

A: 

You could use uints:

uint alwaysPositive = (uint)(largeValue1 + largeValue2) / 2;
Khoth
This will still overflow. The addition overflows.
Orion Adrian
A: 

Not to nitpick, but you mean "integer overflow" rather than "buffer overflow".

I don't know C#, so there may be another way, but you could mimic an unsigned shift by just masking off the top bit: (x >> 1) & 0x80000000

MrZebra
yes, I meant integer overflow
Paco
+1  A: 

You can do it this way:

  x = largeValue1;
  y = largeValue2; 
  return (x&y)+((x^y)/2);

That's a bit-twiddling way to get the average of two integers without overflow.

If you want you can replace the division by two with a bit-shift, but the compiler will do that for you anyways.

Nils Pipenbrinck
+2  A: 
int alwaysPositive = (largeValue1 >> 1) + (largeValue2 >> 1) + (largeValue1 & largeValue2 & 0x01);

The idea behind the above is that if you pre-divide the results before you add them, then you will avoid the overflow as both high-order bits will be unset. You then add some slight correction logic to increase the value by one if both were positive (round down). If you only care if either one was positive (round off) then you could change it to

int alwaysPositive = (largeValue1 >> 1) + (largeValue2 >> 1) + ((largeValue1 | largeValue2) & 0x01);
Orion Adrian
A: 
try
{
    checked { alwaysPositive3 = (largeValue1 + largeValue2); }
}
catch (OverflowException ex)
{
   // Corrective logic
}
ilitirit
What would you fill in for corrective logic here?
Paco
+1  A: 

unchecked((largeValue1 + largeValue2) >> 1) is another option.

See the documentation for the unchecked keyword.

Doug McClean
That will only work if you're using unsigned integers
ilitirit
I don't believe this works. All it does is remove the checking that flags that you have a problem. It doesn't actually remove the problem.
Orion Adrian
I doubt there are many things that only work for unsigned integers. CPUs generally treat signed values the same as signed.
Nefzen