2008-09-22 31 views
5

Quiero que a AlwaysPositive se le asigne un número positivo con todos los valores posibles para lareValue1 y largeValue2 (estos son al menos 1).¿Puedo evitar un desbordamiento de enteros en C# utilizando un desplazamiento a la derecha sin signo?

La siguiente instrucción provoca un desbordamiento de búfer:

int alwaysPositive = (largeValue1 + largeValue2)/2; 

Sé que puedo evitar que restando y sumando:

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

Pero en otros lenguajes de programación puedo utilizar un BitShift sin firmar que hacer el truco:

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

¿Cómo puedo hacer esto en C#?


Las respuestas a continuación resuelven el problema. Probablemente haya muchas formas de hacerlo, pero todas (incluidas mis soluciones) tienen algo en común: todas se ven ofuscadas.

+0

Perdona mi ignorancia, pero ¿por qué querrías hacer esto? –

+0

La razón por la que intenté hacer esto es reinventando la rueda: implementando una búsqueda binaria. ¿Por qué debería escribir mi propia versión? No sé ... – Paco

+0

Solo FYI, las muestras de tu código hacen cosas diferentes. Creo que quieres paréntesis en el primero. PD. ¿Te inspiraste en http://googleresearch.blogspot.com/2006/06/extra-extra-read-all-about-it-nearly.html? –

Respuesta

0

Usted podría utilizar uints:

uint alwaysPositive = (uint)(largeValue1 + largeValue2)/2; 
+0

Esto aún se desbordará. La suma se desborda. –

0

no ser quisquilloso, pero el sentido de "desbordamiento de enteros" en lugar de "buffer overflow".

No sé C#, por lo que no puede ser otra forma, pero se puede imitar un cambio sin firmar con sólo el enmascaramiento de la broca de la parte superior: (x >> 1) & 0x80000000

+0

sí, me refería al desbordamiento de enteros – Paco

2

Usted puede hacerlo de esta manera:

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

Esa es una forma de bits haciendo girar para obtener el promedio de dos números enteros sin rebosadero.

Si lo desea, puede reemplazar la división por dos con un cambio de bit, pero el compilador lo hará por usted de todos modos.

3
int alwaysPositive = (largeValue1 >> 1) + (largeValue2 >> 1) + (largeValue1 & largeValue2 & 0x01); 

La idea detrás de lo anterior es que si usted pre-dividir los resultados antes de añadirlos, entonces usted va a evitar el desbordamiento ya que ambos bits de orden superior será desactivada. A continuación, agregue una ligera lógica de corrección para aumentar el valor en uno si ambos fueron positivos (redondeo hacia abajo). Si sólo se preocupan si uno fue positivo (redondear), entonces podría cambiarlo a

int alwaysPositive = (largeValue1 >> 1) + (largeValue2 >> 1) + ((largeValue1 | largeValue2) & 0x01); 
0
try 
{ 
    checked { alwaysPositive3 = (largeValue1 + largeValue2); } 
} 
catch (OverflowException ex) 
{ 
    // Corrective logic 
} 
+0

¿Qué rellenaría aquí para la lógica correctiva? – Paco

+0

también, si esto estuviera en un bucle interno de un algoritmo, realmente podría ralentizarlo – henon

2

unchecked((largeValue1 + largeValue2) >> 1) es otra opción.

Consulte la documentación del unchecked keyword.

+0

Eso solo funcionará si está usando números enteros sin signo – ilitirit

+0

No creo que esto funcione. Todo lo que hace es eliminar la marca que indica que tienes un problema. En realidad, no elimina el problema. –

+0

Dudo que haya muchas cosas que solo funcionan para enteros sin signo. Las CPU generalmente tratan los valores firmados igual que los firmados. – Nefzen

Cuestiones relacionadas