- 注册时间
- 2007-12-26
- 最后登录
- 1970-1-1
- 威望
- 星
- 金币
- 枚
- 贡献
- 分
- 经验
- 点
- 鲜花
- 朵
- 魅力
- 点
- 上传
- 次
- 下载
- 次
- 积分
- 92615
- 在线时间
- 小时
|
发表于 2008-1-24 20:37:24
|
显示全部楼层
“终极”版本 :)
下面对该问题进行理论推导并尝试推广。
为叙述方便,记 sqrt(2)=j,
数 (a + b*j) 中 a 可称为“有理部”,b 可称为“无理部”。
则 r=0 时,(j-1)^r = (j+1)^(-r) = 1 ± 0*j
当 r>0 时,(j-1)^r = (j+1)^(-r) = ar - br*j = sqrt( kr ) - sqrt( kr - 1 )
当 r<0 时,(j-1)^r = (j+1)^(-r) = ar + br*j = sqrt( kr ) + sqrt( kr - 1 )
楼主所要求的 k = max{ ar^2, 2*br^2 },更一般地:
当 r 为偶数时,kr = ar^2;当 r 为奇数时 kr = 2*br^2
从以上等式可看出,(j-1)^r、(j+1)^r、(j-1)^(-r)、(j+1)^(-r) 的 kr 值彼此相等。
(因为它们的“有理部”、“无理部”绝对值彼此相等)
有了这个结论就好办了,甚至可为下一步程序优化作理论指导,
因为大数同号加法更简单,所以我们尽可能采用“有理部”与“无理部”同号之情形。
(1+j)*(a + b*j) = (a+2*b) + (a+b)*j => br+1 = ar + br, ar+1 = br+1 + br
(a + b*j)^2 = (a^2 + 2*b^2) + 2*a*b*j => a2r = ar^2 + 2*br^2, b2r = 2*ar*br
注意到 ar^2 - 2*br^2 = ±1,所以 a2r 的计算可以少算一次平方。
更好的结论则为 a2r = 2*kr - 1
于是乎,就有了下面的优化算法:- //////////////////////////////////////////////////////////////////////////
- //
- // 目的:快速计算 (sqrt(2) - 1)^r
- // 设计:郭先强 ( gxqcn@163.com; HugeCalc@Gmail.com )
- // 日期:2008-01-24
- // 备注:运行编译好的程序,后面若带参数则输出到文件 Output.txt 中
- //
- // Web: http://www.emath.ac.cn/
- // BBS: http://bbs.emath.ac.cn/
- //
- //////////////////////////////////////////////////////////////////////////
-
- // Project -> Setting -> C/C++ -> Code Generation --> Use run-time library:
- // Win32 Debug: Debug Multithreaded DLL
- // Win32 Release: Multithreaded DLL
-
- #include < iostream.h >
- #include < fstream.h >
-
- #include < HugeCalc.h > // 公共接口
- #include < HugeInt.h > // 10进制系统
- #include < HugeIntX.h > // 16进制系统
-
- #pragma message( "automatic link to .../HugeCalc_API/CppAPI/Lib/HugeCalc.lib" )
- #pragma comment( lib, "HugeCalc.lib" )
-
- int main(int argc, char* argv[])
- {
- cout << "Call " << HugeCalc::GetVer() << endl << endl;
-
- if ( HC_LICENSE_NONE == HugeCalc::GetLicenseLevel() )
- {
- cout << "\r\n警告:您未通过 HugeCalc.dll 的许可认证!\r\n" \
- << "\r\n解决方案可选下列方案之一:" \
- << "\r\n 一、请将本程序移动到“/CopyrightByGuoXianqiang/[../]”目录下运行;" \
- << "\r\n 二、或请在 HugeCalc.chm 中进行注册(一劳永逸)。" \
- << endl;
- }
- else
- {
- #if 1 // 用10进制内核
- CHugeInt a, b, k;
- #else // 用16进制内核
- CHugeIntX a, b, k;
- #endif
- SINT32 r; // r 可正可负
-
- BOOL bSave2File = ( argc > 1 ); // 后面若有参数则存盘
-
- cout << "*** [sqrt(2)-1]^r = sqrt(k) - sqrt(k-1) ***" << endl;
- cout << "input r, output k ...(if r==0, then exit)" << endl;
-
- for ( ; ; )
- {
- cout << endl << "r = ";
- cin >> r;
-
- if ( 0 == r )
- {
- cout << "k = 1" << endl;
- break;
- }
-
- if ( r < 0 ) r = -r;
-
- HugeCalc::EnableTimer();
- HugeCalc::ResetTimer();
-
- // a + b*sqrt(2)
- a = 1;
- b = 1;
- k = 2;
-
- UINT32 i = 1UL << 31;
- while ( i > (UINT32)r )
- {
- i >>= 1;
- }
-
- while ( 0 != ( r & ( i - 1 )))
- {
- ( b *= a ) <<= 1;
- --( a.Swap( k ) <<= 1 );
-
- if ( 0 != ( r & ( i >>= 1 )))
- {
- k = b;
- b += a;
- a.Swap( k ) += b;
-
- ( k = b ).Pow( 2 ) <<= 1;
- }
- else
- {
- ( k = a ).Pow( 2 );
- }
- }
-
- // 变量 a,b 不再使用,清空其所占资源
- a = b = 0;
-
- while ( 1 != i )
- {
- ( --( k <<= 1 )).Pow( 2 );
- i >>= 1;
- }
-
- HugeCalc::EnableTimer( FALSE );
-
- if ( bSave2File )
- {
- ofstream outputFile( "Output.txt", ios::ate );
- if ( outputFile )
- {
- outputFile << endl;
- outputFile << "r = " << r << endl;
- outputFile << "k = " << k.GetStr( FS_NORMAL ) << endl;
- outputFile << "*** k have " << k.GetDigits() << " digits! ***" << endl;
- outputFile << "computation took " << HugeCalc::GetTimerStr() << endl;
- outputFile.close();
- }
- else
- {
- cerr << "File could not be opened" << endl;
- bSave2File = FALSE;
- }
- }
-
- if ( !bSave2File )
- {
- cout << "k = " << k.GetStr( FS_NORMAL ) << endl;
- }
-
- cout << "*** k have " << k.GetDigits() << " digits! ***" << endl;
- cout << "computation took " << HugeCalc::GetTimerStr() << endl;
- }
- }
-
- cout << endl;
- system( "pause" );
-
- return 0;
- }
复制代码 编译好的程序压缩包:(无论注册 HugeCalc 与否均可正常运行;可存盘输出;内含源代码) |
|