如何在C++中避免整数溢出和下溢

如何在C++中避免整数溢出和下溢

在C++中,整数分配了一定数量的位。如果一个整数值占用比分配的位数更多的位,则可能会遇到溢出或下溢。

  1. 整数溢出 发生在数字大于数据类型可以容纳的最大值时。
  2. 整数下溢 发生在数字小于数据类型可以容纳的最小值时。

我们在C++中主要处理这些数据类型以存储整数。它们是:

  1. signed int: 有符号int数据类型的范围为 -2,147,483,6482,147,483,647 (-10的9次方到10的9次方)。
  2. unsigned int: 无符号int数据类型的范围为 04,294,967,295
  3. long long: long long数据类型的范围为 -9,223,372,036,854,775,8089,223,372,036,854,775,807 (-10的18次方到10的18次方)。

接下来让我们详细讨论整数溢出和下溢。

整数溢出

示例: 在下面的C++程序中,三个变量a、b和c被初始化为有符号的int数据类型:

// 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;
}

输出

The product of a and b is 1410065408

时间复杂度: O(1)

辅助空间: O(1)

解释: c的预期值为10的10次方,但输出值是1410065408。这是因为整数c最多能存储10的9次方的范围。

解决方案1:

1. 将变量c初始化为long long数据类型。

long long c = a * b;

2.问题仍然存在,因为a和b都是int数据类型,而两个int数据类型的乘积始终是一个介于int范围内的整数。

3.将a或b初始化为long long数据类型。由于int和long long的乘积是long long。 因此,a和b将产生一个long long范围。

以下是实现上述解决方案以处理整数溢出的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;
}

输出

a和b的积为10000000000

解决方案2:

1. 将变量 c 初始化为 long long 数据类型。

long long c = a * b;

2. 在初始化 c 的值时,我们可以将 ab1LL 相乘,而不是更改它们的数据类型,这样,即使使用 long long 1ab 相乘,也会得到 long long 并将其存储在变量 c 中。

以下是实现上述解决方法以处理整数溢出的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;
}  

输出

a和b的积为10000000000

解决方案3:

将变量a、b和c最初都初始化为 long long 数据类型。这将使我们获得所需的输出,但需要一些额外的内存空间。

以下是实现上述解决方法以处理整数溢出的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;
}  

输出

a和b的积为10000000000

整数下溢

例子1: 在下面的代码中,将3个变量 abc 初始化为无符号整数类型,以显示整数下溢:

// 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;
}  

输出

4294967295

解释:

变量 c 的期望值为 -1 ,但输出为 4294967295 。这是因为 unsigned int c 无法存储负值。

解决方案1:

为了解决上述问题,可以将变量 c 初始化为 int(signed) 类型以存储负数。以下是显示如何处理整数下溢的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;
}  

输出

-1

示例2: 在下面的代码中,变量 a 被初始化为无符号整数,变量 bc 被初始化为整数,以显示整数下溢:

// C++程序演示整数下溢
#include <iostream>
using namespace std;

// 驱动程序
int main()
{
  unsigned int a = 1000000;
  int b = -10000;
  int c = b * a;
  cout << c;
  return 0;
}  

输出结果

-1410065408

解释:

变量 c 的期望值是 -10 10,但实际输出值是 -1410065408 。这是由于有符号整数 c 不能储存小于 -2,147,483,648 的负数值。

解决方案1:

1. 将变量 c 初始化为 long long 数据类型,以存储 -10 10

long long c = b * a;

2. 但是,问题仍存在,因为变量 a 是无符号整数而变量 b 是有符号整数,因此它们的乘积不能是 long long 范围内的任何数字。因此,我们需要将它们中的一个更改为 long long 数据类型。

// C++程序处理整数下溢
#include <iostream>
using namespace std;

// 驱动程序
int main()
{
  unsigned int a = 1000000;
  long long b = -10000;
  long long c = b * a;
  cout << c;
  return 0;
}  

输出结果

-10000000000

解决方案2:

无需更改变量 ab 的数据类型,我们可以在初始化变量 c 的值时将 ab1LL 相乘,这样, ab 乘以长整型1的结果也将变成长整型,并且该值将储存在 long long c .

// C++程序处理整数下溢
#include <iostream>
using namespace std;

// 驱动程序
int main()
{
  unsigned int a = 1000000;
  int b = -10000;
  long long c = b * 1LL * a;
  cout << c;
  return 0;
}  

输出结果

-10000000000

Python教程

Java教程

Web教程

数据库教程

图形图像教程

大数据教程

开发工具教程

计算机教程