[高手请进]-疑似算法精度的问题-梁哥 影子 石头等等 都快来吧
昨天有个朋友发的一个贴 求解
59(X + X平方 + X立方 + X四次方 + X五次方)+1250*X五次方=1000 求解X
我用2分查找的思路做了下来
-- =========================================-- -----------t_mac 小编------------- ---希望有天成为大虾---- -- =========================================create function f_pk(@n float)/*这个函数用来返回59*(@mid + power(@mid,2) + power(@mid,3) + power(@mid,4) + power(@mid,5))+1250* power(@mid,5)每次算出来的值*/ returns float as begin declare @mid float set @mid=@n return 59*(@mid + power(@mid,2) + power(@mid,3) + power(@mid,4) + power(@mid,5))+1250* power(@mid,5) end godeclare @n1 float, @n2 float, @mid float--实现2分查找(具体算法不说了)set @n1=0/*答案一定在0和1之间 具体我已经在http://topic.csdn.net/u/20090624/21/e1a1bba4-3190-4908-aa8f-4f564693109d.html分析过了*/set @n2=1while (@n1< @n2)begin set @mid=(@n1+@n2)/2 print dbo.f_pk(@mid)--调用函数,便于观察运行情况 if( 59*(@mid + power(@mid,2) + power(@mid,3) + power(@mid,4) + power(@mid,5))+1250* power(@mid,5)=1000) break; if(59*(@mid + power(@mid,2) + power(@mid,3) + power(@mid,4) + power(@mid,5))+1250* power(@mid,5)<1000) set @n1=@mid + 0.0001; else set @n2=@mid - 0.0001; end print @mid--输出答案/*96.2188431.749842.6271149.82986.1981065.381025.141005.51995.8161000.65998.233999.4431000.050.909139/*--这个是最后X的值,上面的值是f_pk函数返回的值,可以看到最后判断到1000.05的时候跳出*/*/
#include<iostream>#include<cmath>using namespace std;double T ( double n ) { return 59*(n + pow(n,2.0) + pow(n,3.0) + pow(n,4.0) + pow(n,5.0))+1250* pow(n,5.0);}int main(){ double low = 0, high = 1, mid; while ( low < high ) { mid = ( low + high ) / 2; if ( fabs( T ( mid ) - 1000 ) < 0.000001 ) break; if ( T( mid ) < 1000 ) low = mid + 0.000001; else high = mid - 0.000001; } printf( "%5.6lf\n", mid ); cout << T( mid ) << endl;}
[解决办法]
//C#出來的精度好像更好一些,//看來二分法精度沒有迭代好? double x, y, x1, y1, abs; x = 1.0; abs = 1; while (abs > 0.00000001) { y = 59 * x + 59 * Math.Pow(x, 2) + 59 * Math.Pow(x, 3) + 59 * Math.Pow(x, 4) + 1309 * Math.Pow(x, 5) - 1000; y1 = 59 + 59 * 2 * x + 59 * 3 * Math.Pow(x, 2) + 59 * 4 * Math.Pow(x, 3) + 5 * 1309 * Math.Pow(x, 4); x1 = x - y / y1; abs = Math.Abs(x1-x); x = x1; } Response.Write(x.ToString());//result: 0.909129599424195
[解决办法]
to 楼主:
1、二分法的精度不够,一般编程的时候,与小数比较的时候,不是和0比较,而是和一个很小的数,一般是10的-6此方相比较,即小于0.000001,则可以认为为0
修改你的函数,增加精度以后:
if object_id('f_pk') is not null
drop function f_pk
go
create function f_pk(@n float)/*这个函数用来返回59*(@mid + power(@mid,2) + power(@mid,3) + power(@mid,4) + power(@mid,5))+1250* power(@mid,5)每次算出来的值*/
returns float
as
begin
declare @mid float
set @mid=@n
return 59*(@mid + power(@mid,2) + power(@mid,3) + power(@mid,4) + power(@mid,5))+1250* power(@mid,5)
end
go
declare @n1 float, @n2 float, @mid float--实现2分查找(具体算法不说了)
set @n1=0/*答案一定在0和1之间 具体我已经在http://topic.csdn.net/u/20090624/21/e1a1bba4-3190-4908-aa8f-4f564693109d.html分析过了*/
set @n2=1
while (@n1< @n2)
begin
set @mid=(@n1+@n2)/2
print dbo.f_pk(@mid)--调用函数,便于观察运行情况
if( 59*(@mid + power(@mid,2) + power(@mid,3) + power(@mid,4) + power(@mid,5))+1250* power(@mid,5)=1000)
break;
if(59*(@mid + power(@mid,2) + power(@mid,3) + power(@mid,4) + power(@mid,5))+1250* power(@mid,5)<1000)
set @n1=@mid + 0.000001;
else
set @n2=@mid - 0.000001;
end
print @mid--输出答案
得到的结果为:
96.2188
431.629
842.308
1149.34
985.804
1064.94
1024.73
1005.11
995.417
1000.25
997.832
999.042
999.647
999.95
1000.1
1000.03
999.988
1000.01
999.997
0.909129---这个就是要求的数。
再反带回去:
declare @mid float
set @mid=0.909129
select 59*(@mid + power(@mid,2) + power(@mid,3) + power(@mid,4) + power(@mid,5))+1250* power(@mid,5)
结果为:
999.9970262676 --精度为0.003,你的是0.4.
至于楼主为什么会出现1300,不知道用什么算的?计算器,(我用计算器算出来是0.909139-->>1000.046636),
用计算机的话很可能是你计算的时候采用的数据的精度不够