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

编译时直接计算数列存入constexpr变量,避免重复计算素数长度

编译期生成素数并存储到constexpr变量的优化方案

核心问题解决方案

1. 无需预先计算大小的编译期存储

在C++20及以后,std::vector支持constexpr操作,可直接在编译期用它收集素数,无需预先知晓元素数量。若坚持使用std::array,也能基于constexpr vector的编译期size()值来构造array,全程在编译阶段完成。

2. 避免重复计算(移除get_primes_size函数)

原代码两次遍历判断素数,造成重复计算。通过一次遍历同时完成素数收集与数量统计即可解决:先用constexpr vector存储所有素数,再转换为array,每个数仅需调用一次is_prime判断。

3. 编译期std::vector转std::array的可行性

完全可行,C++20及以上版本中,constexpr vector的size()是编译期常量,可直接用于指定array的大小,再通过编译期循环完成元素复制。

优化后的代码示例

#include <array>
#include <vector>
#include <iostream>

constexpr bool is_prime(int n)
{
    if (n <= 1) return false;
    if (n == 2) return true;
    if (n % 2 == 0) return false;
    // 修正原函数边界问题:i*i <=n 避免漏判平方数
    for (int i = 3; i * i <= n; i += 2) {
        if (n % i == 0) {
            return false;
        }
    }
    return true;
}

template <int UpperLimit>
consteval auto get_primes()
{
    std::vector<int> temp_primes;
    // 一次遍历完成素数收集
    for (int i = 2; i <= UpperLimit; ++i) {
        if (is_prime(i)) {
            temp_primes.push_back(i);
        }
    }
    // 编译期将vector转换为array
    std::array<int, temp_primes.size()> primes_arr{};
    for (std::size_t idx = 0; idx < temp_primes.size(); ++idx) {
        primes_arr[idx] = temp_primes[idx];
    }
    return primes_arr;
}

// 编译期生成素数数组
constexpr auto primes = get_primes<1000>();

int main()
{
    std::cout << "1000以内素数总数:" << primes.size() << '\n';
    for (int prime : primes) {
        std::cout << prime << ' ';
    }
    std::cout << '\n';
    return 0;
}

代码说明

  • 修正原is_prime函数的边界错误:原代码i*i < n会漏判4、9这类平方数,改为i*i <=n并增加偶数快速判断,提升效率。
  • 使用consteval确保函数完全在编译期执行,不会生成运行时代码。
  • 仅一次遍历收集素数,避免了原代码两次调用素数判断的重复计算。
  • 借助C++20的constexpr vector特性,先动态收集素数再转换为固定大小的array,兼顾灵活性与性能。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.06 04:05:38