一篇关于质数的讨论
2026-06-19 00:09:43
发布于:广东
已知:在宏观统计意义上,质数的出现可以近似看作相互独立的随机事件
因此是否可以考虑泊松分布来估计质数整体的趋势?
这是一个大概的代码:
#include<windows.h>
#include<iostream>
#include<cstring>
#include<cmath>
using namespace std;
const int N = 1e7;
const int interval = 1e3;
const int Div = 1;
bool prime[N+5];
void color(int a)
{
SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),a);
/*
1 深蓝色
2 深绿色
3 深青色
4 深红色
5 深粉色
6 黄色
7 深白色
8 灰色
9 浅蓝色
10 浅绿色
11 浅青色
12 浅红色
13 浅粉色
14 浅黄色
15 浅白色
背景
1~15 黑色
16~31 深蓝色
32~47 深绿色
48~63 深青色
64~79 深红色
'S'~95 深粉色
96~111 深黄色
112~127 深白色
128~143 灰色
144~159 浅蓝色
160~1'A' 浅绿色
176~191 浅青色
192~207 浅红色
208~223 浅粉色
224~239 浅黄色
240~255 浅白色
*/
}
void init()
{
memset(prime,true,sizeof(prime));
prime[0] = prime[1] = false;
for(int i=2;i<=N;i++)
{
if(prime[i])
{
for(int j=2;i*j<=N;j++)
{
prime[i*j] = false;
}
}
}
}
int get(int current_i, int interval_length) {
// 边界保护:防止传入过小的值导致 log(1)=0 或负数
if (current_i < 2 || interval_length < 1) {
return 0;
}
// 质数密度约为 1 / ln(x),区间内期望个数 = 区间长度 / ln(x)
double lambda = static_cast<double>(interval_length) / std::log(static_cast<double>(current_i));
// 四舍五入返回整数(C++14 标准库支持 std::round)
return static_cast<int>(std::round(lambda));
}
int main()
{
// freopen("test_out.out","w",stdout);
init();
int cnt = 0;
for(int i=1;i<=N;i++)
{
if(prime[i]) cnt++;
if(i%interval==0)
{
// cout<<i<<" ";
color(1);
for(int j=1;j<=cnt/Div;j++) cout<<"*";
cout<<"\n";
color(4);
int data = get(i,interval);
for(int j=1;j<=data/Div;j++) cout<<"*";
cnt = 0;
cout<<"\n\n";
}
}
return 0;
}
更专业的泊松分布
#include <windows.h>
#include <iostream>
#include <cstring>
#include <cmath>
#include <fstream>
#include <vector>
using namespace std;
const int N = 1e7;
const int interval = 1000;
bool prime[N + 5];
void init() {
memset(prime, true, sizeof(prime));
prime[0] = prime[1] = false;
for (int i = 2; i <= N; i++) {
if (prime[i]) {
for (int j = 2; i * j <= N; j++) {
prime[i * j] = false;
}
}
}
}
int get_theory(int current_i, int interval_length) {
if (current_i < 2 || interval_length < 1) return 0;
double lambda = (double)interval_length / log((double)current_i);
return (int)(lambda + 0.5);
}
int main() {
system("title 正在生成质数分布曲线图...");
cout << "正在筛法计算质数 (1千万) ..." << endl;
init();
cout << "筛法完成,正在生成曲线数据 ..." << endl;
// 收集数据
vector<int> xs, actuals, theories;
int cnt = 0;
for (int i = 1; i <= N; i++) {
if (prime[i]) cnt++;
if (i % interval == 0) {
xs.push_back(i);
actuals.push_back(cnt);
theories.push_back(get_theory(i, interval));
cnt = 0;
}
}
cout << "数据点个数: " << xs.size() << endl;
cout << "正在生成 HTML 曲线图 ..." << endl;
// ========== 生成 HTML 文件 ==========
ofstream html("prime_curve.html");
html << "<!DOCTYPE html>\n";
html << "<html>\n<head>\n";
html << "<meta charset=\"UTF-8\">\n";
html << "<title>质数分布曲线 vs 素数定理</title>\n";
html << "<style>\n";
html << " body { background: #1a1a2e; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0; font-family: sans-serif; }\n";
html << " .container { background: #16213e; padding: 30px; border-radius: 16px; box-shadow: 0 0 40px rgba(0,150,255,0.2); }\n";
html << " canvas { display: block; background: #0f3460; border-radius: 8px; box-shadow: inset 0 0 30px rgba(0,0,0,0.5); }\n";
html << " .legend { color: #eee; padding: 10px 0; text-align: center; font-size: 16px; }\n";
html << " .legend span { display: inline-block; padding: 4px 16px; margin: 0 10px; border-radius: 4px; }\n";
html << " .legend .actual { background: #4fc3f7; color: #000; }\n";
html << " .legend .theory { background: #ff5252; color: #fff; }\n";
html << "</style>\n";
html << "</head>\n<body>\n";
html << "<div class=\"container\">\n";
html << "<canvas id=\"chart\" width=\"1200\" height=\"600\"></canvas>\n";
html << "<div class=\"legend\">\n";
html << " <span class=\"actual\">● 实际质数个数 (每" << interval << "个数字)</span>\n";
html << " <span class=\"theory\">● 素数定理预测 (区间长度 / ln(x))</span>\n";
html << " <span style=\"color:#aaa; font-size:14px;\"> | 横轴: 数字范围 (0 ~ 1000万) 纵轴: 质数个数</span>\n";
html << "</div>\n";
html << "</div>\n";
html << "<script>\n";
// 将 C++ 数据序列化为 JavaScript 数组
html << "const xs = [";
for (size_t i = 0; i < xs.size(); i++) {
if (i > 0) html << ",";
html << xs[i];
}
html << "];\n";
html << "const actual = [";
for (size_t i = 0; i < actuals.size(); i++) {
if (i > 0) html << ",";
html << actuals[i];
}
html << "];\n";
html << "const theory = [";
for (size_t i = 0; i < theories.size(); i++) {
if (i > 0) html << ",";
html << theories[i];
}
html << "];\n";
// ========== JavaScript 绘图逻辑 ==========
html << R"(
const canvas = document.getElementById('chart');
const ctx = canvas.getContext('2d');
const W = canvas.width, H = canvas.height;
const pad = { top: 40, bottom: 50, left: 70, right: 30 };
const plotW = W - pad.left - pad.right;
const plotH = H - pad.top - pad.bottom;
// 计算纵轴范围 (留10%余量)
let maxVal = 0;
for (let v of actual) if (v > maxVal) maxVal = v;
for (let v of theory) if (v > maxVal) maxVal = v;
maxVal = Math.ceil(maxVal * 1.1);
// 坐标转换函数
function toPixel(x, y) {
const px = pad.left + (x / xs[xs.length-1]) * plotW;
const py = pad.top + plotH - (y / maxVal) * plotH;
return [px, py];
}
// 背景网格
ctx.strokeStyle = '#2a4a7f';
ctx.lineWidth = 0.5;
for (let i = 0; i <= 10; i++) {
const x = pad.left + (i / 10) * plotW;
ctx.beginPath();
ctx.moveTo(x, pad.top);
ctx.lineTo(x, pad.top + plotH);
ctx.stroke();
}
for (let i = 0; i <= 5; i++) {
const y = pad.top + (i / 5) * plotH;
ctx.beginPath();
ctx.moveTo(pad.left, y);
ctx.lineTo(pad.left + plotW, y);
ctx.stroke();
}
// 坐标轴标签
ctx.fillStyle = '#88ccff';
ctx.font = '14px sans-serif';
ctx.textAlign = 'center';
for (let i = 0; i <= 10; i++) {
const val = Math.round((i / 10) * xs[xs.length-1] / 10000) * 10000;
const x = pad.left + (i / 10) * plotW;
ctx.fillText(val / 10000 + '万', x, pad.top + plotH + 25);
}
ctx.textAlign = 'right';
for (let i = 0; i <= 5; i++) {
const val = Math.round((i / 5) * maxVal);
const y = pad.top + plotH - (i / 5) * plotH;
ctx.fillText(val, pad.left - 10, y + 5);
}
ctx.textAlign = 'center';
ctx.fillStyle = '#aaddff';
ctx.font = '16px sans-serif';
ctx.fillText('数字范围 (x)', W/2, H - 5);
// 绘制实际曲线 (蓝色, 半透明细线)
ctx.beginPath();
ctx.strokeStyle = '#4fc3f7';
ctx.lineWidth = 1.2;
ctx.globalAlpha = 0.8;
for (let i = 0; i < xs.length; i++) {
const [px, py] = toPixel(xs[i], actual[i]);
if (i === 0) ctx.moveTo(px, py);
else ctx.lineTo(px, py);
}
ctx.stroke();
// 绘制理论曲线 (红色, 加粗)
ctx.beginPath();
ctx.strokeStyle = '#ff5252';
ctx.lineWidth = 3.0;
ctx.globalAlpha = 1.0;
for (let i = 0; i < xs.length; i++) {
const [px, py] = toPixel(xs[i], theory[i]);
if (i === 0) ctx.moveTo(px, py);
else ctx.lineTo(px, py);
}
ctx.stroke();
// 绘制图例小圆点 (覆盖在Canvas上)
ctx.globalAlpha = 1;
ctx.fillStyle = '#4fc3f7';
ctx.beginPath();
ctx.arc(950, 30, 6, 0, 2*Math.PI);
ctx.fill();
ctx.fillStyle = '#ff5252';
ctx.beginPath();
ctx.arc(950, 60, 6, 0, 2*Math.PI);
ctx.fill();
ctx.fillStyle = '#fff';
ctx.font = '14px sans-serif';
ctx.textAlign = 'left';
ctx.fillText('实际', 965, 36);
ctx.fillText('理论', 965, 66);
console.log('绘制完成! 点数量: ' + xs.length);
)";
html << "</script>\n</body>\n</html>";
html.close();
cout << "========================================" << endl;
cout << "? 生成成功!" << endl;
cout << "请找到当前目录下的 prime_curve.html 文件," << endl;
cout << "双击用浏览器打开即可看到高清曲线图!" << endl;
cout << "========================================" << endl;
// 自动打开浏览器(可选)
system("start prime_curve.html");
return 0;
}
全部评论 1
不如其他更适合质数的估算函数吧
3天前 来自 广东
0

















有帮助,赞一个