C++ :整形数防止数据溢出

C++ 学习笔记:整形数防止数据溢出

C/C++ 中的算术及其陷阱
https://www.cnblogs.com/kongj/p/14612362.html
数据溢出的处理方法,怎样防止数据溢出?

用 INT_MAX, 无法直接用 n > INT_MAX 来判断数据溢出,因为此时 n 已经溢出。
需要提前预判!
比如,a接近溢出,a * b 之后会大于INT_MAX的话,我们提前判断,
a * b > INT_MAX 改为 a > INT_MAX / b

所以总结以下3点:

  • 如果整数很容易超出(比如阶乘),程序需要有提前预判的措施
  • int 的最大数值非常小,只有约20个亿左右!(2**31 - 1)
  • 如果需要用到比较大的数,尽量用 int64_t (即 long long, 最大值2**63 - 1, 900亿亿左右),
  • 如果是数组索引,可以用std::size_t, (如果是vector, deque之类的标准库容器,用vector<T>::size_type类型的整数可以保证索引值覆盖容器大小)

典型例子是阶乘,整数很容易溢出,

  • 13阶乘 > INT_MAX
  • 21阶乘 > LLONG_MAX
    需要预判防止溢出,
    如以下代码,分别提供了 int 版本(32位)和 long long 版本(64位)
    代码中的if (res > INT_MAX / i) 用于防止溢出。
    long long 版本的 INT_MAX 是 LLONG_MAX
#include <iostream>
using namespace std;

/*
    factorial, very likely to exceed in limit of int,
    use INT_MAX to prevent this data overflow error.
*/

int factorial(int n) {
    
    int res = 1;
    for (int i = 1; i != (n + 1); ++i) {
        if (res > INT_MAX / i) {
            cerr << "\033[31;1m Error, data overflow. \033[0m" << endl;
            return INT_MAX;
        } else {
            res *= i;
        }
    }
    return res;
}


int64_t factorial_llong(int n) {
    /// int64_t (= long long) version of int, 
    /// use LLONG_MAX instead of INT_MAX
    int64_t res = 1;
    for (int i = 1; i != (n + 1); ++i) {
        if (res > LLONG_MAX / i) {
            cerr << "\033[31;1m Error, data overflow. \033[0m" << endl;
            return LLONG_MAX;
        } else {
            res *= i;
        }
    }
    return res;
}


int main() {

    /// LLONG_MAX is the long long version of INT_MAX
    cout << "INT_MAX = " << INT_MAX << endl;  // 2147483647 = 2**31 - 1
    cout << "LONG_MAX = " << LONG_MAX << endl;  // 2147483647 = 2**31 - 1
    cout << "LLONG_MAX = " << LLONG_MAX << endl;  // 9223372036854775807 = 2**63 - 1

    auto a = 1;
    while (1) {
        cout << "a = ";
        cin >> a;
        cout << "got a = " << a << endl;
        if (a == 0) break;

        cout << "\033[35;1m factorial(a) = \033[0m" << factorial(a) << endl;
        cout << "\033[35;1m factorial_llong(a) = \033[0m" << factorial_llong(a) << endl << endl;
    }   
    return 0;
}

另外, mark一下,对于单双精度的浮点数,其能够表示的最大最小数值可以看这里https://blog.csdn.net/K346K346/article/details/50487127

  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值