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

为何大数值下C语言因数查找程序错误输出2的幂次?

问题根源:整数溢出导致的未定义行为

你的程序出现异常的核心原因不是内存耗尽,而是32位int类型的整数溢出,具体细节拆解如下:

1. 输入值超出int的取值范围

在绝大多数系统中,int是32位有符号整数,它的取值范围是 -2^31 到 2^31-1(也就是 -2147483648 到 2147483647,约2e9)。当你输入1e10或更大的数时,这个值远超出int能容纳的上限,scanf("%d", &inp)会触发整数溢出——这属于C语言中的未定义行为。

溢出后,inp会被赋予一个错误的“绕回”值(通常是输入值对2^32取模后的结果),而这个值大概率是一个2的幂数(比如你看到的2、4、16等)。你的程序实际上是在处理这个错误的小值,而非你输入的大数,自然会输出一堆2的幂因数。

2. 数组分配与输出逻辑的次要问题

你用calloc(inp/4, sizeof(int))分配存储因数的数组,当inp溢出后,inp/4的计算结果完全错误:

  • 如果溢出后的inp是很小的正数,会分配一个极小的数组,可能无法容纳所有因数,导致数组越界(又是未定义行为);
  • 如果溢出后的inp是负数,inp/4会被calloc当作无符号数处理,可能分配一个超大数组,但这不是你遇到的核心问题。

另外,你用while(arr[j] != 0)终止输出的逻辑也不可靠:虽然calloc会把数组初始化为0,但如果因数填满数组后覆盖了后续的0,或者数组越界读取到非0值,都会导致输出异常。

修复方案

要处理1e10甚至更大的数,你需要把所有涉及存储大数的变量改成64位整数类型long long,同时调整输入输出格式:

#include <stdio.h>
#include <stdlib.h>

int main() {
    long long inp;
    int size = 0;
    puts("Enter a number: ");
    // 使用%lld读取long long类型
    scanf("%lld", &inp);
    
    // 因数数量最多不超过inp的一半,用inp/2作为数组大小更稳妥
    long long *arr = (long long*) calloc(inp/2, sizeof(long long));
    if (arr == NULL) {
        printf("Memory allocation failed!\n");
        return 1;
    }
    
    // 循环变量i也要用long long,避免遍历过程中溢出
    for(long long i = 2; i <= inp; i++){
        if (inp % i == 0){
            arr[size] = i;
            size++;
        }
    }
    
    // 直接用记录的因数数量size控制输出,比判断arr[j]!=0更可靠
    for(int j = 0; j < size; j++){
        printf("%lld\n", arr[j]);
    }
    
    free(arr);
    return 0;
}

额外说明:如果要处理更大的数(比如1e18),单纯遍历判断因数的效率会很低,你可以优化算法(比如只遍历到sqrt(inp),同时记录对应的配对因数),但这属于性能优化的范畴了。

内容的提问来源于stack exchange,提问作者vinod-vms

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 07:35:14