求圆周率第n位的函数
Function to find the nth digit of Pi
我一直想找到一个算法做到这一点。我不在乎它有多慢,只要它能返回Pi的第n位:
,
size_t piAt(long long int n)
{
}
最好不要使用无穷级数。
如果有人有这样的函数或类,在C或c++中,我真的很有兴趣看到它。
谢谢
这是由Fabrice Bellard编写的Simon Plouffe的解决方案:
/*
* Computation of the n'th decimal digit of pi with very little memory.
* Written by Fabrice Bellard on January 8, 1997.
*
* We use a slightly modified version of the method described by Simon
* Plouffe in "On the Computation of the n'th decimal digit of various
* transcendental numbers" (November 1996). We have modified the algorithm
* to get a running time of O(n^2) instead of O(n^3log(n)^3).
*
* This program uses mostly integer arithmetic. It may be slow on some
* hardwares where integer multiplications and divisons must be done
* by software. We have supposed that 'int' has a size of 32 bits. If
* your compiler supports 'long long' integers of 64 bits, you may use
* the integer version of 'mul_mod' (see HAS_LONG_LONG).
*/
#include <stdlib.h>
#include <stdio.h>
#include <math.h>
/* uncomment the following line to use 'long long' integers */
/* #define HAS_LONG_LONG */
#ifdef HAS_LONG_LONG
#define mul_mod(a,b,m) (( (long long) (a) * (long long) (b) ) % (m))
#else
#define mul_mod(a,b,m) fmod( (double) a * (double) b, m)
#endif
/* return the inverse of x mod y */
int inv_mod(int x, int y)
{
int q, u, v, a, c, t;
u = x;
v = y;
c = 1;
a = 0;
do {
q = v / u;
t = c;
c = a - q * c;
a = t;
t = u;
u = v - q * u;
v = t;
} while (u != 0);
a = a % y;
if (a < 0)
a = y + a;
return a;
}
/* return (a^b) mod m */
int pow_mod(int a, int b, int m)
{
int r, aa;
r = 1;
aa = a;
while (1) {
if (b & 1)
r = mul_mod(r, aa, m);
b = b >> 1;
if (b == 0)
break;
aa = mul_mod(aa, aa, m);
}
return r;
}
/* return true if n is prime */
int is_prime(int n)
{
int r, i;
if ((n % 2) == 0)
return 0;
r = (int) (sqrt(n));
for (i = 3; i <= r; i += 2)
if ((n % i) == 0)
return 0;
return 1;
}
/* return the prime number immediatly after n */
int next_prime(int n)
{
do {
n++;
} while (!is_prime(n));
return n;
}
int main(int argc, char *argv[])
{
int av, a, vmax, N, n, num, den, k, kq, kq2, t, v, s, i;
double sum;
if (argc < 2 || (n = atoi(argv[1])) <= 0) {
printf("This program computes the n'th decimal digit of \pin"
"usage: pi n , where n is the digit you wantn");
exit(1);
}
N = (int) ((n + 20) * log(10) / log(2));
sum = 0;
for (a = 3; a <= (2 * N); a = next_prime(a)) {
vmax = (int) (log(2 * N) / log(a));
av = 1;
for (i = 0; i < vmax; i++)
av = av * a;
s = 0;
num = 1;
den = 1;
v = 0;
kq = 1;
kq2 = 1;
for (k = 1; k <= N; k++) {
t = k;
if (kq >= a) {
do {
t = t / a;
v--;
} while ((t % a) == 0);
kq = 0;
}
kq++;
num = mul_mod(num, t, av);
t = (2 * k - 1);
if (kq2 >= a) {
if (kq2 == a) {
do {
t = t / a;
v++;
} while ((t % a) == 0);
}
kq2 -= a;
}
den = mul_mod(den, t, av);
kq2 += 2;
if (v > 0) {
t = inv_mod(den, av);
t = mul_mod(t, num, av);
t = mul_mod(t, k, av);
for (i = v; i < vmax; i++)
t = mul_mod(t, a, av);
s += t;
if (s >= av)
s -= av;
}
}
t = pow_mod(10, n - 1, av);
s = mul_mod(s, t, av);
sum = fmod(sum + (double) s / (double) av, 1.0);
}
printf("Decimal digits of pi at position %d: %09dn", n,
(int) (sum * 1e9));
return 0;
}
C:tcc>tcc -I libtcc libtcc/libtcc.def -run examples/pi.c 1
Decimal digits of pi at position 1: 141592653
C:tcc>tcc -I libtcc libtcc/libtcc.def -run examples/pi.c 1000
Decimal digits of pi at position 1000: 938095257
http://bellard.org/pi/pi_n2/pi_n2.html 这个出色的解决方案展示了如何在O(N)时间和O(log·N)空间内计算π的N位,并且不需要计算它之前的所有数字。
哦,它是十六进制的。
如果你不想这样做,你可以很容易地从shell中完成:
% perl -Mbignum=bpi -wle 'print bpi(20)'
3.1415926535897932385
% perl -Mbignum=bpi -wle 'print bpi(50)'
3.1415926535897932384626433832795028841971693993751
% perl -Mbignum=bpi -wle 'print bpi(200)'
3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170679821480865132823066470938446095505822317253594081284811174502841027019385211055596446229489549303820
% perl -Mbignum=bpi -wle 'print bpi(1000)'
3.141592653589793238462643383279502884197169399375105820974944592307816406286208998628034825342117067982148086513282306647093844609550582231725359408128481117450284102701938521105559644622948954930381964428810975665933446128475648233786783165271201909145648566923460348610454326648213393607260249141273724587006606315588174881520920962829254091715364367892590360011330530548820466521384146951941511609433057270365759591953092186117381932611793105118548074462379962749567351885752724891227938183011949129833673362440656643086021394946395224737190702179860943702770539217176293176752384674818467669405132000568127145263560827785771342757789609173637178721468440901224953430146549585371050792279689258923542019956112129021960864034418159813629774771309960518707211349999998372978049951059731732816096318595024459455346908302642522308253344685035261931188171010003137838752886587533208381420617177669147303598253490428755468731159562863882353787593751957781857780532171226806613001927876611195909216420199
包括这个在内的几个解决方案实际上是从第n位开始打印几个数字。
有一个很好的(而且比以前的答案快得多)解决方案:http://numbers.computation.free.fr/Constants/Algorithms/pidec.cpp
代码只需要修改"typedef int64 ModInt;"
typepedef int64_t ModInt;"gcc pidec.cpp && time echo 20000 | ./a.out
Pidec, direct computation of decimal digits of pi at a given position n.
(http://numbers.computation.free.fr/Constants/constants.html for more details)
Enter n : Parameters : M=122, N=7094, M*N+M=872562
Series time : 0.17
Digits of pi after n-th decimal digit : 203856539
Total time: 0.68
real 0m0.691s
user 0m0.678s
sys 0m0.006s
Compilation finished at Wed Feb 3 13:34:48
这是在2015年初"macbook pro。
相关文章:
- "error: no matching function for call to"构造函数错误
- 什么时候调用组成单元对象的析构函数
- 继承函数的重载解析
- 为什么随机数生成器不在void函数中随机化数字,而在main函数中随机化
- C++模板来检查友元函数的存在
- 递归函数计算序列中的平方和(并输出过程)
- 对RValue对象调用的LValue ref限定成员函数
- C++17复制构造函数,在std::unordereded_map上进行深度复制
- 将数组作为参数传递给函数安全吗?作为第三方职能部门,可以探索他们想要的之外的其他元素
- 在C++STL中是否有Polyval(Matlab函数)等价物?
- 为什么使用 "this" 指针调用派生成员函数?
- 将对象数组的引用传递给函数
- 函数调用中参数的顺序重要吗
- 函数向量_指针有不同的原型,我可以构建一个吗
- 使用不带参数的函数访问结构元素
- 代码在main()中运行,但在函数中出现错误
- 内置函数可查看CPP中的成员变量
- 如何获取std::result_of函数的返回类型
- 如何在c++中为模板函数实例创建快捷方式
- 求圆周率第n位的函数