¿Cómo evitar los desbordamientos y subdesbordamientos de enteros en C++?

Los enteros en C++ se asignan con un cierto número de bits. Si un valor entero toma más bits que el número de bits asignado, entonces podemos encontrarnos con un desbordamiento o subdesbordamiento.

  1. El desbordamiento de enteros ocurre cuando un número es mayor que el valor máximo que puede contener el tipo de datos.
  2. El subdesbordamiento de enteros se produce cuando un número es menor que el valor mínimo que puede contener el tipo de datos. 

Nos ocupamos principalmente de estos tipos de datos para almacenar números enteros en C++. Estos son:

  1. int firmado: el tipo de datos int firmado oscila entre -2.147.483.648 y 2.147.483.647 (-10 9 a 10 9 ).
  2. int sin firmar: el tipo de datos int sin firmar oscila entre 0 y 4,294,967,295 .
  3. long long: el tipo de datos long long oscila entre -9 223 372 036 854 775 808 y 9 223 372 036 854 775 807 (-10 18 y 10 18 ).

Analicemos el desbordamiento de enteros y el subdesbordamiento de enteros en detalle.

Desbordamiento de enteros

Ejemplo: en el siguiente programa de C++, tres variables a, b y c se inicializan como tipo de datos int (con signo) :

C++

// C++ program to demonstrate 
// integer overflow
#include <iostream>
using namespace std;
  
// Driver code
int main()
{
    int a = 100000;
    int b = 100000;
    int c = a * b;
    cout << "The product of a and b is " << 
             c << endl;
    return 0;
}
Producción

The product of a and b is 1410065408

Explicación: el valor esperado de c es 10 10 pero el resultado es 1410065408 . Esto se debe a que int c puede almacenar un rango máximo de 10 9 .

Solución 1:

1. Inicialice la variable c como tipo de datos long long

largo largo c = a * b;

2. Pero el problema aún surge porque a y b son tipos de datos int y el producto de dos tipos de datos int siempre es un número entero que se encuentra entre el rango de int mencionado anteriormente. 

3. Inicialice aob como tipos de datos long long . Dado que la multiplicación de int y long long es long long . Entonces, a y b darán como resultado un rango largo largo

A continuación se muestra el programa C++ para implementar la solución anterior para manejar el desbordamiento de enteros:

C++

// C++ program to handle integer 
// overflow
#include <iostream>
using namespace std;
  
// Driver code
int main()
{
    int a = 100000;
    
    // Changed int b to long long b 
    long long b = 100000; 
    long long c = a * b;
    cout << "The product of a and b is " << 
             c << endl;
    return 0;
}
Producción

The product of a and b is 10000000000

Solución 2: 

1. Inicialice la variable c como tipo de datos long long

largo largo c = a * b;

2. En lugar de cambiar los tipos de datos de a y b , podemos multiplicar a y b con 1LL mientras inicializamos el valor de c para que la multiplicación de a y b con long long 1 también resulte en long long y ese valor se almacenará en largo largo c. 

A continuación se muestra el programa C++ para implementar la solución anterior para manejar el desbordamiento de enteros:

C++

// C++ program to handle integer
// overflow
#include <iostream>
using namespace std;
  
// Driver code
int main()
{
    int a = 100000;
    int b = 100000;
    
      // Here we multiplied 'a' with 1LL 
    // which results into long long 
    // which is further multiplied with 'b'
    long long c = a * 1LL * b;
    cout << "The product of a and b is " << 
             c << endl;
    return 0;
}
Producción

The product of a and b is 10000000000

Solución 3: inicialice las tres variables a, b y c como tipos de datos long long inicialmente. Dará nuestra salida deseada pero tomará algo de espacio extra. 

A continuación se muestra el programa C++ para implementar la solución anterior para manejar el desbordamiento de enteros:

C++

// C++ program to handle integer
// overflow
#include <iostream>
using namespace std;
  
// Driver code
int main()
{
      // Here we changed the data types 
    // of both a and b to long long 
    // to avoid overflow
    long long a = 100000, b = 100000;
    long long c = a * b;
    cout << "The product of a and b is " << 
             c << endl;
    return 0;
}
Producción

The product of a and b is 10000000000

Subdesbordamiento de enteros

Ejemplo 1: en el siguiente código, se inicializan 3 variables a , b y c y luego como unsigned int para mostrar el subdesbordamiento de enteros:

C++

// C++ program to show integer 
// underflow
#include <iostream>
using namespace std;
  
// Driver code
int main()
{
    unsigned int a = 4, b = 5;
    unsigned int c = a - b;
    cout << c;
    return 0;
}
Producción

4294967295

Explicación: 

El valor esperado de c es -1 pero la salida es 4294967295 . Esto se debe a que el int c sin signo no puede almacenar un valor negativo.

Solución 1:

Para solucionar el problema anterior, inicialice c como int (firmado) para almacenar un número negativo. A continuación se muestra el programa C++ para mostrar cómo manejar el subdesbordamiento de enteros:

C++

// C++ program to show how to 
// handle integer underflow
#include <iostream>
using namespace std;
  
// Driver code
int main()
{
    unsigned int a = 4, b = 5;
    
    // Here we changed data type of 
    // c to signed int
    int c = a - b; 
    cout << c;
    return 0;
}
Producción

-1

Ejemplo 2: en el siguiente código, la variable a se inicializa como int sin signo, b y c se inicializan como int para mostrar el subdesbordamiento de enteros:

C++

// C++ program to show integer
// underflow
#include <iostream>
using namespace std;
  
// Driver code
int main()
{
    unsigned int a = 1000000;
    int b = -10000;
    int c = b * a;
    cout << c;
    return 0;
}
Producción

-1410065408

Explicación: 

El valor esperado de c es -10 10 pero la salida es -1410065408 . Esto se debe a que int(signed) c no puede almacenar un valor negativo menor que -2,147,483,648. 

Solución 1:

1. Inicialice la variable c como tipo de datos long long para almacenar -10 10 .

largo largo c = b * a;

2. Pero el problema aún surge como puede ver a continuación porque a es un int sin signo mientras que b es un int con signo y el producto de ambos no puede ser un número en el rango de long long , por lo que debemos cambiar uno de ellos a un tipo de datos largo largo .

A continuación se muestra el programa C++ para manejar el subdesbordamiento de enteros:

C++

// C++ program to handle 
// integer underflow
#include <iostream>
using namespace std;
  
// Driver code
int main()
{
    unsigned int a = 1000000;
    long long b = -10000;
    long long c = b * a;
    cout << c;
    return 0;
}
Producción

-10000000000

Solución 2:

En lugar de cambiar los tipos de datos de a y b , podemos multiplicar a y b con 1LL mientras inicializamos el valor de c para que la multiplicación de a y b con long long 1 también resulte en long long y ese valor se almacenará en long long c . 

C++

// C++ program to handle 
// integer underflow
#include <iostream>
using namespace std;
  
// Driver code
int main()
{
    unsigned int a = 1000000;
    int b = -10000;
    long long c = b * 1LL * a;
    cout << c;
    return 0;
}
Producción

-10000000000

Publicación traducida automáticamente

Artículo escrito por divyansh2212 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *