You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Rust中检查阿姆斯特朗数遇整数溢出panic,该如何处理?

处理阿姆斯特朗数检查中的整数溢出问题

你在Exercism上的阿姆斯特朗数检查代码触发了整数溢出panic,错误信息如下:

thread 'properly_handles_overflow' panicked at 'attempt to add with overflow', src/lib.rs:9:9

原代码:

use std::io;
pub fn is_armstrong_number(mut num: u32) -> bool {
    let check = num;
    let mut sum = 0;
    let length = (num as f64).log(10.0).floor() as u32 + 1;

    while num != 0 {
        let digit = num % 10;
        sum += u32::pow(digit, length);
        num = num / 10;
    }
    if sum == check {
        return true;
    } else {
        return false;
    }
}

fn main() {
    let mut input = String::new();
    io::stdin().read_line(&mut input);
    let number: u32 = input.trim().parse().unwrap();

    is_armstrong_number(number);
}

问题原因

Rust默认在debug模式下会检查整数运算溢出并触发panic。原代码中,当计算u32::pow(digit, length)时,若结果超出u32的最大值(4294967295),或者累加后sum超出u32范围,就会触发溢出错误。

解决方案

1. 使用更宽的整数类型存储总和

将sum的类型改为u64,利用其更大的存储空间避免溢出,最后再与原数比较:

pub fn is_armstrong_number(mut num: u32) -> bool {
    let check = num;
    let mut sum: u64 = 0;
    let length = (num as f64).log(10.0).floor() as u32 + 1;

    while num != 0 {
        let digit = num % 10;
        sum += u64::from(u32::pow(digit, length));
        num = num / 10;
    }
    sum == u64::from(check)
}

2. 使用溢出安全的方法检查运算

Rust提供了checked_pow和checked_add方法,它们在溢出时返回None,可直接以此判定结果:

pub fn is_armstrong_number(mut num: u32) -> bool {
    let check = num;
    let mut sum = 0;
    let length = (num as f64).log(10.0).floor() as u32 + 1;

    while num != 0 {
        let digit = num % 10;
        // 幂运算溢出则直接返回false
        let pow_result = match digit.checked_pow(length) {
            Some(p) => p,
            None => return false,
        };
        // 累加溢出也返回false
        sum = match sum.checked_add(pow_result) {
            Some(s) => s,
            None => return false,
        };
        num = num / 10;
    }
    sum == check
}

3. 优化位数计算+溢出安全处理

原代码用浮点log(10)计算位数可能存在精度误差,改用循环计算位数,同时结合溢出检查:

pub fn is_armstrong_number(mut num: u32) -> bool {
    let check = num;
    let mut temp = num;
    let mut length = 0;

    // 循环计算位数,避免浮点精度问题
    while temp != 0 {
        length += 1;
        temp /= 10;
    }
    // 处理0的特殊情况
    if length == 0 {
        return true;
    }

    let mut sum = 0;
    temp = num;
    while temp != 0 {
        let digit = temp % 10;
        match digit.checked_pow(length) {
            None => return false,
            Some(p) => {
                sum = match sum.checked_add(p) {
                    Some(s) => s,
                    None => return false,
                };
            }
        }
        temp /= 10;
    }
    sum == check
}

内容的提问来源于stack exchange,提问作者user14473720

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.08 13:47:46