有偿求助:编写统计园内整点个数的程序
输出园半径R的园内整点个数,园周率精确到40位有效值,
2022-05-19 17:39
2022-05-20 08:32
[此贴子已经被作者于2022-5-21 23:40编辑过]
2022-05-21 22:33

2022-05-22 06:00
[此贴子已经被作者于2022-5-22 08:45编辑过]
2022-05-22 08:39
程序代码:#include <math.h>
#include <assert.h>
// 对一个整数开根号,这是效率的关键所在,但我使用了最烂的方法,只为了验证算法的正确性
unsigned long long sqrtint( unsigned long long n )
{
unsigned long long r = (unsigned long long)sqrt( n*1.0 );
// 因为sqrt精度不足,所以需要校正
if( r*r > n )
for( --r; r*r>n; --r );
else if( r*r < n )
for( ; (r+1)*(r+1)<=n; ++r );
return r;
}
// 求 x^2 + y^2 <= RR 整数解的数目, 结果大约是 PI*RR
unsigned long long foo( unsigned long long RR )
{
unsigned long long r = sqrtint( RR );
unsigned long long w = sqrtint( RR/2 );
unsigned long long t = 0;
for( unsigned long long i=w+1; i<=r; ++i )
t += sqrtint( RR - i*i );
unsigned long long result = (2*w+1)*(2*w+1) + 4*(r-w) + 8*t;
// 上述表达式可能产生数据溢出,另一种方法是在函数入口就限定 RR*PI必须小于unsigned long long所能表达的最大数
assert( (2*w+1)*(2*w+1)/(2*w+1) == (2*w+1) );
assert( result > 4*(r-w) + 8*t );
return result;
}
#include <stdio.h>
int main( void )
{
assert( foo(10) == 37 );
assert( foo(100) == 317 );
assert( foo(1000) == 3149 );
assert( foo(10000) == 31417 );
assert( foo(100000) == 314197 );
assert( foo(1000000) == 3141549 );
assert( foo(10000000) == 31416025 );
assert( foo(100000000) == 314159053 );
assert( foo(1000000000) == 3141592409 );
assert( foo(10000000000) == 31415925457 );
assert( foo(100000000000) == 314159264013 );
assert( foo(1000000000000) == 3141592649625 );
assert( foo(10000000000000) == 31415926532017 );
assert( foo(100000000000000) == 314159265350589 );
assert( foo(1000000000000000) == 3141592653588533 );
assert( foo(10000000000000000) == 31415926535867961 );
assert( foo(100000000000000000) == 314159265358987341 );
printf( "f(10^18) = %llu\n", foo(1000000000000000000) );
printf( "f(10^19) = %llu\n", foo(10000000000000000000) );
}[此贴子已经被作者于2022-5-22 13:55编辑过]
2022-05-22 13:54
2022-05-22 21:13
2022-05-22 23:28
2022-05-23 01:08
2022-05-23 08:40