圆周率计算
2026-09-24 21:07:05
发布于:广东
#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <iomanip>
#include <chrono>
#include <cmath>
#include <windows.h>
using namespace std;
// ==========================================
// 高精度整数类
// ==========================================
class BigInt {
public:
vector<int> digits; // 低位在前
BigInt() {}
BigInt(long long v) {
if (v == 0) digits.push_back(0);
while (v > 0) {
digits.push_back(v % 10);
v /= 10;
}
}
void trim() {
while (digits.size() > 1 && digits.back() == 0)
digits.pop_back();
if (digits.empty()) digits.push_back(0);
}
BigInt operator+(const BigInt& b) const {
BigInt res;
int carry = 0;
size_t len = max(digits.size(), b.digits.size());
for (size_t i = 0; i < len || carry; ++i) {
int sum = carry;
if (i < digits.size()) sum += digits[i];
if (i < b.digits.size()) sum += b.digits[i];
res.digits.push_back(sum % 10);
carry = sum / 10;
}
return res;
}
BigInt operator-(const BigInt& b) const {
BigInt res;
int borrow = 0;
for (size_t i = 0; i < digits.size(); ++i) {
int sub = digits[i] - borrow;
if (i < b.digits.size()) sub -= b.digits[i];
if (sub < 0) { sub += 10; borrow = 1; }
else { borrow = 0; }
res.digits.push_back(sub);
}
res.trim();
return res;
}
BigInt operator*(int v) const {
if (v == 0) return BigInt(0);
BigInt res;
long long carry = 0;
for (size_t i = 0; i < digits.size() || carry; ++i) {
long long prod = carry;
if (i < digits.size()) prod += (long long)digits[i] * v;
res.digits.push_back(prod % 10);
carry = prod / 10;
}
res.trim();
return res;
}
BigInt divide(int v, int& remainder) const {
BigInt res;
remainder = 0;
res.digits.resize(digits.size(), 0);
for (int i = (int)digits.size() - 1; i >= 0; --i) {
long long cur = (long long)remainder * 10 + digits[i];
res.digits[i] = cur / v;
remainder = cur % v;
}
res.trim();
return res;
}
string toString() const {
string s;
for (auto it = digits.rbegin(); it != digits.rend(); ++it)
s += char('0' + *it);
return s;
}
// 快速判断是否为0,用于提前终止循环
bool isZero() const {
return digits.size() == 1 && digits[0] == 0;
}
};
// ==========================================
// 计算 arctan(1/x) - 修复进度与时间显示
// ==========================================
BigInt computeArctan(int x, int prec, const string& name, chrono::steady_clock::time_point global_start) {
int scale = prec + 20; // 保护位
BigInt power;
power.digits.resize(scale + 1, 0);
power.digits[scale] = 1;
int rem;
BigInt term = power.divide(x, rem);
BigInt sum = term;
int x2 = x * x;
int k = 1;
bool pos = false;
// 【修复1】估算总项数留足余量,避免实际项数超过预估值
double log_x = log10((double)x);
int estimated_total_terms = (int)(prec / (2 * log_x)) + 100;
cout << "[" << name << "] 开始计算..." << endl;
auto step_start = chrono::steady_clock::now();
int last_reported_k = 0;
int items_since_last = 0;
while (true) {
k += 2;
term = term.divide(x2, rem);
// 【修复2】用快速判断终止,避免多跑无用项
if (term.isZero()) break;
BigInt ct = term.divide(k, rem);
if (ct.isZero()) break;
if (pos) sum = sum + ct;
else sum = sum - ct;
pos = !pos;
items_since_last++;
// 【修复3】每 200 项刷新一次,平衡性能与显示
if (k - last_reported_k >= 1) {
auto now = chrono::steady_clock::now();
chrono::duration<double> elapsed_step = now - step_start;
double precision_per_term = 2 * log_x;
int estimated_digits = (int)(k * precision_per_term);
if (estimated_digits > prec) estimated_digits = prec;
// 【修复4】修复时间计算报错:显式转换为 double
double time_per_item = 0.0;
if (items_since_last > 0) {
time_per_item = static_cast<double>(elapsed_step.count()) / items_since_last;
}
int remaining_items = estimated_total_terms - k;
if (remaining_items < 0) remaining_items = 0;
double eta_seconds = remaining_items * time_per_item;
// 计算总已用秒数
chrono::duration<double> total_elapsed = now - global_start;
double total_sec = total_elapsed.count();
// 【修复5】未真正跑完前,进度最高只显示99%,杜绝“100%还在跑”
int progress = (int)((double)k / estimated_total_terms * 100);
if (progress >= 100) progress = 99;
cout << "\r [" << name << "] "
<< setw(3) << progress << "% | "
<< "项: " << setw(6) << k << "/" << estimated_total_terms << " | "
<< "精度: ~" << setw(6) << estimated_digits << "/" << prec << " | "
<< "已用: " << fixed << setprecision(1) << total_sec << "s | "
<< "预计剩余: " << fixed << setprecision(1) << eta_seconds << "s " << flush;
last_reported_k = k;
items_since_last = 0;
step_start = now;
}
}
// 最终状态:循环真正结束后才打印100%
cout << "\r [" << name << "] 100% | 项: " << k << " | 精度: " << prec << " | 完成! " << endl;
cout << "[" << name << "] 计算结束。" << endl;
return sum;
}
// ==========================================
// 主函数
// ==========================================
int main() {
SetConsoleOutputCP(CP_UTF8);
cout << "你想算到多少位:";
int n;
cin >> n;
if (n <= 0){
cout << "输入不合规";
return 0;
}
cout << "=== 计算圆周率 Pi (" << n << " 位) ===" << endl;
auto global_start = chrono::steady_clock::now();
// 带进度条计算
BigInt a5 = computeArctan(5, n, "Atan(1/5)", global_start);
BigInt a239 = computeArctan(239, n, "Atan(1/239)", global_start);
// 合并结果
cout << "正在合并最终结果 (16*atan5 - 4*atan239)..." << endl;
BigInt pi = (a5 * 16) - (a239 * 4);
auto end_calc = chrono::steady_clock::now();
// 输出结果
string piStr = pi.toString();
cout << "\nPi = ";
// 逐位输出效果
for (size_t i = 0; i < piStr.length(); ++i) {
cout << piStr[i];
if (i == 0) cout << ".";
if ((i + 1) % 50 == 0) {
cout.flush();
}
}
cout << endl;
auto end_total = chrono::steady_clock::now();
cout << "\n--- 统计信息 ---" << endl;
cout << "计算核心耗时: " << fixed << setprecision(2)
<< chrono::duration<double>(end_calc - global_start).count() << " 秒" << endl;
cout << "总程序耗时: " << fixed << setprecision(2)
<< chrono::duration<double>(end_total - global_start).count() << " 秒" << endl;
cout << "结果位数: " << piStr.length() << " 位" << endl;
return 0;
}
全部评论 2
6
1周前 来自 浙江
0。
2026-09-17 来自 浙江
0






























有帮助,赞一个