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

如何优化计算2^p的程序以支持p>1,000,000?

大指数2^p计算的性能优化方案

问题背景

现有计算2^p的程序仅支持p≤50000,希望扩展到p>1000000。已通过预定义数组替代malloc提升了速度,但双层循环中的除法、取模运算成为性能瓶颈,去前导零和打印逻辑无问题。原代码如下:

#include <stdio.h>

unsigned int p, l, zero;

int main() {

int power2[50005] = { 0 };
int product[50005] = { 0 };
int carry[50005] = { 0 };
            
printf("Enter power: ");
scanf("%u", &p);
l = (p * 0.4) + 1;
                
power2[l-1] = 2;

for (int j=p-2; j>-1; --j) {
    for (int i=l-1; i>-1; --i) {
        
        power2[i] *= 2;
        carry[i] = power2[i] / 10;
        
        product[i] = power2[i] + carry[i+1];
        
        carry[i] = product[i] / 10;
        product[i] %= 10;
        
        power2[i] = product[i];
            
    }
}
/* remove 0s from beginning of final array - product[] */       
zero = 0;
while (product[zero] == 0) {
    ++zero;
} 
for (int i=zero; i<l; ++i) {
    printf("%d", product[i]);
}

printf("\n");
return 0;
}

核心优化思路

原代码的问题在于冗余的数组操作和重复的除法/取模计算,针对这些痛点做如下优化:

  • 合并冗余数组,减少内存开销:原代码同时维护power2、product、carry三个数组,完全可以简化为一个存储数字的数组+单个进位变量,大幅减少内存读写操作。
  • 简化进位逻辑,减少除法/取模次数:每个数位仅需一次乘2、加进位、取模(求当前位)、除法(求新进位),避免原代码中多次重复的除法和取模。
  • 精确计算数组尺寸:用更准确的log10(2)值计算2^p的位数,避免数组空间浪费或不足;预定义数组时直接设置对应最大p的足够尺寸。
  • 提前终止无效循环:当进位为0时,高位无需再遍历,直接跳出循环减少无用计算。

优化后的代码

#include <stdio.h>

// 对应p=1e6时,2^p的位数约为301030,预留额外空间防止溢出
#define MAX_DIGITS 301035  

int main() {
    unsigned int p, zero, len;
    int digits[MAX_DIGITS] = {0};
    
    printf("Enter power: ");
    scanf("%u", &p);
    
    // 精确计算2^p的位数:floor(p*log10(2)) + 1
    len = (unsigned int)(p * 0.30102999566) + 1;
    digits[len - 1] = 2;  // 初始值为2^1,后续需乘p-1次2得到2^p
    
    for (unsigned int j = 1; j < p; ++j) {
        int carry = 0;
        for (int i = len - 1; i >= 0; --i) {
            int temp = digits[i] * 2 + carry;
            digits[i] = temp % 10;
            carry = temp / 10;
            
            // 进位为0时,高位无需处理,直接跳出循环
            if (carry == 0) {
                break;
            }
        }
        // 若最后仍有进位,说明结果位数增加
        if (carry > 0) {
            digits[--len] = carry;
        }
    }
    
    // 去除前导零
    zero = 0;
    while (digits[zero] == 0 && zero < len) {
        ++zero;
    }
    
    // 打印结果
    for (unsigned int i = zero; i < len; ++i) {
        printf("%d", digits[i]);
    }
    printf("\n");
    
    return 0;
}

额外说明

  • 若需要支持更大的p(如2e6),只需调整MAX_DIGITS为对应位数+5即可(2e6的位数约为602060)。
  • 优化后的代码将除法/取模的执行次数减少了约一半,同时减少了数组间的赋值操作,性能提升显著,足以支撑p>1e6的计算需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.18 16:25:12