leetcode题目: Reverse Integer 的C语言解法

本文介绍了一个经典的整数反转问题及其解决方案。通过两个不同的实现方式,详细探讨了如何处理整数反转过程中的数值溢出问题,并给出了简洁高效的代码示例。

题目的链接

Given a 32-bit signed integer, reverse digits of an integer.

Example 1:

Input: 123
Output: 321
Example 2:

Input: -123
Output: -321
Example 3:

Input: 120
Output: 21
Note:
Assume we are dealing with an environment which could only hold integers within the 32-bit signed integer range. For the purpose of this problem, assume that your function returns 0 when the reversed integer overflows.

题目算不得难,但写的时候也出现了挺多问题。数值溢出是一个我没有考虑到的问题。因为定义的函数是int类型,而int的存储范围为2^31,需要一个位置来放符号,即实际范围为 -2147483648~2147483647。也就是题设最后说明的 如果数字倒置后数值溢出则返回0 这一情况。

#include <stdio.h>
#include <math.h>

int reverse(int x) {
    int i = 0, j = 0;
    long int sum = 0;
    long int tem = abs(x);

    while (tem != 0 )
    {
        tem = tem / 10;
        j++;
    }

    tem = abs(x);

    while (tem != 0) {
        i = tem % 10;
        tem = (tem - i) / 10;
        j--;
        sum = sum + i * pow(10, j);

    }

    if (x < 0) 
         sum = -sum;

    if (sum < -2147483648 || sum >2147483647)
        return 0;
    else
        return sum;
}

int main()
{
    int x = -123;

    printf("%d\n", reverse(x));
    return 0;
}

程序中调用的函数也就几个幂函数以及绝对值函数,虽然有些繁琐,但用来解决符号方面可能出现的问题还是挺直观的。在最后的调试环节,我开始还是用的老方法,打断点后逐步执行找到数值突变的点(也就是数值溢出发生的语句),不过在这种类型题中有一种更为简单的调试方法:在循环后直接打印输出数值,找到错误后再把输出语句给删除。这样比逐步执行要简便且直观的多。

最后再附上哥哥写的简便版代码:

#include <limits.h>

int reverse(int x)
{
    long long re = 0;
    while(x){
        re = re * 10 + x % 10;
        x /= 10;
    }
    return re > INT_MIN && re < INT_MAX ? re : 0;
}

这个思路要比我的要简便很多。我的想法是逐步先遍历出数字的位数,之后每次取余好让这个数字倒置过来,这样就多了一轮循环。re不用int定义,直接就避免溢出,最后在return时再进行判定,倘若是溢出的值则返回0,否则就直接输出。

<think>好的,我现在需要解决用户提出的Error 10904 (KEY+904)整数溢出问题。首先,我得理解这个错误的具体原因和背景。用户提到这是一个整数溢出问题,并提到了机器限制和双精度解决方案。我的思路应该是先确定错误发生的场景,然后分析可能的原因,最后给出解决方法。 首先,整数溢出通常发生在计算过程中,当数值超过了变量类型所能表示的范围。例如,使用32位有符号整数时,最大值是2,147,483,647,如果计算结果超过这个值就会溢出。用户提到的KEY+904可能是指错误代码中的特定部分,需要结合具体环境来看,但这里可能只是错误标识符的一部分,具体含义可能依赖于特定的系统或库。 接下来,用户提到“machine limits double precision solution”,这可能意味着在尝试使用双精度浮点数来解决溢出问题。不过,双精度浮点数虽然能表示更大范围的数值,但可能存在精度损失的问题,尤其是在处理非常大的整数时。例如,双精度浮点数的有效位数约为15-17位,超过这个位数的整数无法精确表示。 现在,我需要考虑可能的解决方案。首先,检查变量类型是否足够大。如果原先是使用int32_t,可能需要升级到int64_t,以扩大整数范围。其次,如果数值确实超过了64位整数的范围,可能需要改用高精度库或任意精度算术,比如GMP库。另外,如果问题出在计算过程中,可能需要优化算法,避免中间结果溢出,比如分步计算或使用模运算。 然后,用户提供的引用内容中提到了使用inttypes.h中的宏来处理整数类型,确保不做出假设。这可能提示在代码中正确使用固定宽度整数类型,并配合适当的格式字符串,避免类型不匹配导致的未定义行为。另外,引用2中提到的版本更新和向后兼容性问题,可能暗示在系统更新时需要注意库的版本兼容性,确保使用的解决方案在目标环境中可行。 可能的错误场景示例:例如在C/C++中,使用了int32_t类型的变量存储一个超过2^31-1的值,导致溢出。或者在进行乘法运算时,两个int32_t相乘的结果超过32位,即使存储在int64_t中,也需要先将操作数转换为更大的类型。 解决方案步骤可能包括: 1. 审查代码,找到触发溢出的变量和计算步骤。 2. 将变量类型改为更大的类型,如int64_t或uint64_t。 3. 使用高精度库处理超大整数。 4. 优化计算逻辑,分步处理或采用模运算减少中间值的大小。 5. 检查系统或库的版本,确保使用的函数支持所需的数值范围。 另外,用户的问题可能与特定的库或框架相关,比如数据库中的整数溢出,或者某个API的限制。需要更多的上下文信息,但根据现有信息,可以给出通用的解决步骤。 最后,需要验证解决方案是否有效,例如通过单元测试或逐步调试,确保溢出问题被解决,并且没有引入新的问题,如精度损失或性能下降。</think>### Error 10904 (KEY+904) 整数溢出问题的分析与解决 #### 问题分析 该错误通常由**整数溢出**引发,即程序中的整数值超出了当前变量类型的表示范围。例如: - 使用`int32_t`时,最大值为$2^{31}-1 = 2,147,483,647$,超出后会导致溢出[^1]。 - 在计算过程中(如乘法、累加),中间结果可能超过变量类型的存储能力。 #### 解决步骤 1. **确认溢出位置** - 检查代码中涉及大整数操作的逻辑(如循环累加、乘法、数组索引)。 - 使用调试工具(如GDB)或日志定位具体溢出点。 2. **升级变量类型** - 将`int32_t`改为`int64_t`(范围:$-9.2 \times 10^{18}$到$9.2 \times 10^{18}$): ```c #include <inttypes.h> int64_t large_value = 9223372036854775807LL; // 使用明确的后缀LL printf("Value: %" PRId64 "\n", large_value); // 使用inttypes.h的格式宏 ``` 3. **使用双精度浮点数的注意事项** - 虽然`double`可表示更大范围(如$\pm1.7 \times 10^{308}$),但**整数精度仅限53位**: $$ \text{最大精确整数} = 2^{53} \approx 9 \times 10^{15} $$ - 示例:当数值超过$2^{53}$时,`double`会丢失精度: ```c double d1 = 9007199254740992.0; // 2^53,可精确表示 double d2 = d1 + 1; // 结果仍为9007199254740992.0 ``` 4. **高精度计算需求** - 若数值超过$2^{64}$或需要精确计算,需使用高精度库(如GMP): ```c #include <gmp.h> mpz_t huge_number; mpz_init(huge_number); mpz_set_str(huge_number, "123456789012345678901234567890", 10); ``` 5. **算法优化** - 分治策略:将大数拆分为多个部分计算(如FFT加速乘法)。 - 模运算优化:对中间结果取模避免溢出,例如: $$ (a \times b) \mod m = [(a \mod m) \times (b \mod m)] \mod m $$ #### 验证与测试 - 添加边界值测试用例(如$2^{31}-1, 2^{63}-1$)。 - 使用静态分析工具(如Clang Sanitizer)检测溢出: ```bash clang -fsanitize=integer -g example.c ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值