c++ - with - ¿Cómo comprobar si A+B superan largo tiempo?(Tanto A como B son largas largas)
quiero ver en ingles (4)
Además, si solo lo está utilizando para la depuración, puede usar el siguiente ''truco'' para leer el bit de desbordamiento de la última operación directamente (suponiendo que su compilador / CPU admita esto):
int flags;
_asm {
pushf // push flag register on the stack
pop flags // read the value from the stack
}
if (flags & 0x0800) // bit 11 - overflow
...
Esta pregunta ya tiene una respuesta aquí:
- ¿Cómo detectar el desbordamiento de enteros? 31 respuestas
Tengo 2 números: A
y B
Necesito calcular A+B
en algún lugar de mi código. Tanto A
como B
son long long
, y pueden ser positivos o negativos .
Mi código se ejecuta de forma incorrecta y sospecho que el problema ocurre al calcular A+B
Simplemente quiero comprobar si A+B
excede el long long
alcance. Por lo tanto, cualquier método es aceptable, ya que solo lo uso para la depuración.
Algo como lo siguiente:
long long max = std::numeric_limits<long long>::max();
long long min = std::numeric_limits<long long>::min();
if(A < 0 && B < 0)
return B < min - A;
if(A > 0 && B > 0)
return B > max - A;
return false;
Podemos razonar sobre esto de la siguiente manera:
Si
A
yB
son signos opuestos, no pueden desbordarse: el mayor que cero debería ser mayor que elmax
o el menor que cero debería ser menor que elmin
.En los otros casos, basta con el álgebra simple.
A + B > max => B > max - A
se desbordará si ambos son positivos. De lo contrario, si ambos son negativos,A + B < min => B < min - A
El desbordamiento es posible solo cuando ambos números tienen el mismo signo. Si ambos son positivos, entonces tiene un desbordamiento si matemáticamente A + B > LLONG_MAX
, o equivalentemente B > LLONG_MAX - A
Como el lado derecho no es negativo, la última condición ya implica B > 0
. El argumento análogo muestra que, en el caso negativo, tampoco es necesario verificar el signo de B
(gracias a Ben Voigt por señalar que el control de signos en B
es innecesario). Entonces puedes comprobar
if (A > 0) {
return B > (LLONG_MAX - A);
}
if (A < 0) {
return B < (LLONG_MIN - A);
}
return false;
para detectar el desbordamiento. Estos cálculos no pueden desbordarse debido a las comprobaciones iniciales.
Verificar el signo del resultado de A + B
funcionaría con la semántica envolvente garantizada de los cálculos de enteros desbordados. Pero el desbordamiento de enteros con signo es un comportamiento indefinido, e incluso en las CPU en las que la envoltura es el comportamiento implementado, el compilador puede asumir que no ocurre un comportamiento indefinido y eliminar la verificación de desbordamiento cuando se implementa de esta manera. Así que el cheque sugerido en los comentarios a la pregunta es altamente poco confiable.
Enmascare los signos, conviértalos a valores sin firmar y realice la suma. Si está por encima de 1 << (sizeof(int) * 8 - 1)
entonces tiene un desbordamiento.
int x, y;
if (sign(x) == sign(y)){
unsigned int ux = abs(x), uy = abs(y);
overflow = ux + uy >= (1 << (sizeof(int) * 8 - 1));
}
Mejor aún, vamos a escribir una plantilla:
template <typename T>
bool overflow(signed T x, signed T y){
unsigned T ux = x, uy = y;
return ( sign(x) == sign(y) && (ux + uy >= (1 << (sizeof(T) * 8 - 1)));
}