有偿求助:编写统计园内整点个数的程序
输出园半径R的园内整点个数,园周率精确到40位有效值,
[此贴子已经被作者于2022-5-21 23:40编辑过]
[此贴子已经被作者于2022-5-22 08:45编辑过]
#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编辑过]