int类型 计算时溢出问题!

Java整型溢出与处理
本文详细解析了Java中整型数据溢出的现象及原因,通过实例展示了int类型达到极限值时的行为,并介绍了如何避免溢出,包括使用long类型进行强制转换的方法。

在java中

代码  

   //不满一小时舍去  有效期
  int days = (int) ((expiredTime.getTime() - date.getTime()) / (1000 * 3600));

数据的溢出:

当整数的数据大小超出了可以表示的范围,而程序中又没有做数值范围的检查时,

这个整型变量所输出的值将发生紊乱,且不是预期的运行结果。

01 //  整数值如果超出了自己所可以表示范围的最大值,会出现溢出 

//        int a = -2147483648;
//        System.out.println("a-1 = " + (a - 1));
//        System.out.println("a-2 = " + (a - 2));
//
//        int b = 2147483647;
//        System.out.println("b+1 = " + (b + 1));
//        System.out.println("b+2 = " + (b + 2));

输出结果: 
a-1 = 2147483647
a-2 = 2147483646
b+1 = -2147483648
b+2 = -2147483647


     当最大值加上 1 时,结果反而变成表示范围中最小的值;当最大值加上 2 时,结
果变成表示范围中次小的值,这就是数据类型的溢出。读者可以发现,这个情形会出
现一个循环,若是想避免这种情况的发生,在程序中就必须加上数值范围的检查功能,
或者使用较大的表示范围的数据类型,如长整型。

    就像计数器的内容到最大值时会自动归零一样。而在整数中最小值为
-2147483648,所以当整数 x 的值最大时,加上 1 就会变成最小值-2147483648,也就
是产生了溢出。

        为了避免 int 类型的溢出,可以在该表达式中的任一常量后加上大写的“L”,或
是在变量前面加上 long,作为强制类型的转换。


递归计算强转int  溢出的最后值
public static int a(long d) {
    long e = 0;
    if (d > 2147483647) {
        e = -(d - 2147483647);
        a(e);
    } else if (d < -2147483648) {
        e = -(d + 2147483647 + 1);
        a(e);
    }
    return (int) e;
}

 

<think>我们正在讨论C++中int类型乘法溢出问题及解决方案。根据引用内容,int类型乘法溢出发生在两个int相乘的结果超出int类型所能表示的范围(-2147483648到2147483647)。即使将结果赋给long long类型变量,由于乘法运算本身已经溢出(因为两个int操作数在运算int类型进行,结果也是int,此溢出已经发生),所以不会得到正确结果。 解决方案: 1. 将操作数之一转换为更大的整数类型(如long long),这样整个表达式会按照更大的类型进行计算。 2. 使用更大的整数类型(如long long)来存储操作数,避免使用int进行大数运算。 接下来,我们将详细解释问题并给出示例代码。 </think> ### C++中`int`类型乘法溢出问题及解决方案 #### 1. 问题本质与原理 当两个`int`类型变量相乘,若结果超出`int`的表示范围($-2^{31} \sim 2^{31}-1$ 即 $-2147483648 \sim 2147483647$),会发生**整数溢出**。关键特性: 1. **静默溢出**:不触发异常或警告,结果被截断为32位[^2][^3] ```cpp int a = 50000; int b = 60000; int result = a * b; // 期望3e9,实际-64771072(溢出) ``` 2. **类型提升失效**:即使赋值给更大类型,运算仍按`int`处理[^1][^4] ```cpp long long result = a * b; // 仍溢出!因a*b先以int计算 ``` #### 2. 错误案例分析 ```cpp // 场景:计算 92599395 * 31(引用[4]案例) int hash = 92599395 * 31; // 期望:2870581245 // 实际:-1424386051(溢出后截断) ``` **原理分析**: 1. 运算编译器按`int`处理,中间结果$2870581245 > 2147483647$($2^{31}-1$) 2. 超出部分被截断,按补码解释为负数[^3] #### 3. 解决方案 ##### (1) 显式类型转换(推荐) ```cpp int a = 50000; int b = 60000; long long result = static_cast<long long>(a) * b; // 正确:3e9 ``` - **原理**:提前提升操作数类型,避免中间溢出[^1][^5] - **适用范围**:已知单个操作数范围 ##### (2) 使用更大类型存储操作数 ```cpp long long a = 50000; long long b = 60000; long long result = a * b; // 安全 ``` - **优势**:彻底避免整型溢出风险 - **注意**:输入/输出需匹配类型(如`scanf("%lld", &a)`) ##### (3) 编译器内置函数(GCC/Clang) ```cpp int a = INT_MAX; int b = 2; if (__builtin_mul_overflow(a, b, &result)) { // 处理溢出 } ``` - **原理**:运行检测溢出标志位 - **局限**:编译器依赖性强 #### 4. 预防措施 1. **输入验证**: ```cpp if (a > 0 && b > 0 && a > INT_MAX / b) { // 处理溢出 } ``` 2. **使用安全库**: ```cpp #include <safeint.h> msl::utilities::SafeInt<int> sa(a); auto result = sa * b; // 溢出抛异常 ``` 3. **编译器警告**: ```bash g++ -Wall -Wextra -Wconversion # 启用溢出警告 ``` #### 数学原理 溢出本质是模运算: $$ \text{result} = (a \times b) \mod 2^{32} $$ 当$|a \times b| \geq 2^{31}$,符号位被破坏导致结果异常。 > ⚠️ **关键结论**:C++整数运算以操作数类型为准,而非目标变量类型。强制提前类型转换是解决溢出的核心方法[^1][^5]。 --- **图:乘法溢出示意图** ``` 正常范围: [ -2³¹, 2³¹-1 ] ┌──────────────┬──────────────┐ │ 负溢出区 │ 正溢出区 │ 计算结果 →│← 截断为负数 │← 截断为正数 →│ └──────────────┴──────────────┘ -2147483648 0 2147483647 ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值