当前位置: 代码迷 >> Sql Server >> []-疑似算法精度的有关问题-梁哥 影子 石头等等 都快来吧
  详细解决方案

[]-疑似算法精度的有关问题-梁哥 影子 石头等等 都快来吧

热度:208   发布时间:2016-04-27 19:10:42.0
[高手请进]-疑似算法精度的问题-梁哥 影子 石头等等 都快来吧
昨天有个朋友发的一个贴 求解
59(X + X平方 + X立方 + X四次方 + X五次方)+1250*X五次方=1000 求解X
我用2分查找的思路做了下来 
SQL code
-- =========================================-- -----------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 @[email protected] 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=(@[email protected])/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 @[email protected] + 0.0001;  else  set @[email protected] - 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的时候跳出*/*/

问题来了:
我把0.909139 放于计算式进行检验 发现
59(X + X平方 + X立方 + X四次方 + X五次方)+1250*X五次方=1300多
误差这么大 到底什么原因
我也试过将 @n1 float, @n2 float, @mid float都变成 decimal类型的 都差不多 
这个是不是SQL SERVER的一个精度缺失问题
我试过用C语言的方法进行同样得到方法(一模一样)但是答案确非常接近~~
高手不要在潜水 都来吧~


 
 

------解决方案--------------------
C/C++ code
#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# code
//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 @[email protected]
 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)
  相关解决方案