Fortran Coder

查看: 9322|回复: 4
打印 上一主题 下一主题

[讨论] 函数体构造对数值精度的过度反应

[复制链接]

13

帖子

6

主题

0

精华

熟手

F 币
114 元
贡献
81 点
跳转到指定楼层
楼主
发表于 2014-3-4 19:08:06 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
[Fortran] 纯文本查看 复制代码
program main

implicit none

        real*8 :: Cd0,m,Vcruise,Rho,f1,f2,f3,f4,f5,f6,parent1,parent2,parent3,pi,funcval

!        c=1.0d0
        pi=4.0d0*datan(1.0d0)
        Vcruise=150.0d0
        m=1000.0d0
        Cd0=0.02d0
        Rho=1.212d0
        funcval=0.0d0
        parent1=11.34
        parent2=0.67
        parent3=32.83

        f1=parent1/parent2  !aspect ratio
        f2=parent1*parent2  !wing planform area
!        f3=(((Wbp+4.936*f2*(f3**0.3)*9.81)*2)/(Rho*f2*(Vmin**2)))**2 !lift coefficient function (for minimum air speed)
        f4=2.0d0*m*9.81d0/(Rho*f2*(Vcruise**2))  !lift coefficient

        if (parent3.le.30.0d0 .and. f1.gt.2.27d0 ) then
            f5=1.78d0*(1.0d0-0.045d0*(f1**0.68d0))-0.64d0  !Oswald Coefficient for sweep angle smaller than or equals to 30 Degree,f1 cannot be smaller than 2.27
        elseif (parent3.gt.30.0d0 .and. f1.gt.10.0d0) then
            f5=4.61d0*(1.0d0-0.045d0*(f1**0.68d0))*((dcos(parent3*pi/180.0d0))**0.15d0)-3.1d0  !Oswald Coefficient for sweep angle larger than 30 Degree
        else 
            f5=0.8d0   
        endif

        f6=Cd0+(f4**2)/(pi*f1*f5)  !drag coefficient

        funcval=dble(Rho*(Vcruise**2)*f2*f6/2)  

        write(*,*) funcval
        pause
end


        以上函数实例,目前parent1,parent2,parent3给出的数值都为双精度小数点后两位有效数字,此时计算结果正确显示。
        如果尝试人为或程式化直接产生parent1,parent2,parent3的双精度或单精度数值,则计算结果非正常显示。
        此例子说明了在fortran编译器中,当函数或算式分母可能是非常小的实数时,参数的类型及计算误差会造成整体计算错误,所以应尽量回避这种情况。比如F=1/f。另外还可以人为添加约束条件。针对本例,主要问题集中于函数f5,对f5加入适当约束,比如f5小于0或一个给定值的时候,强制给定f5等于一个较大的数,可以有效解决计算失效的问题;或者可以将对应参数parent1,parent2,parent3的值强制截断为小数点后保留两位有效数字,命令如下:

        parent(i)=(dint(parent(i)*100.0d0))/100.0d0

分享到:  微信微信
收藏收藏 点赞点赞 点踩点踩

136

帖子

3

主题

0

精华

版主

F 币
1964 元
贡献
1677 点

帅哥勋章管理勋章爱心勋章新人勋章热心勋章元老勋章

沙发
发表于 2014-3-4 23:47:50 | 只看该作者
没看明白
回复

使用道具 举报

13

帖子

6

主题

0

精华

熟手

F 币
114 元
贡献
81 点
板凳
 楼主| 发表于 2014-3-5 01:41:46 | 只看该作者
函数计算的时候,参数的数据类型和精度会影响函数的计算结果,尤其是当作除法的时候,如果分子很大,分母很小,那么会出现计算结果不正确的情况。而此时编译器在编译执行过程中并不报错。我帖子里描述的很清楚了,你自己赋值黏贴代码,然后自己编译执行以下,之后自己在三个参数parent的数值后面随便加一些不是0的数字,按双精度长度加,之后重新编译执行,就会看到错误结果。加的越多,错误越离谱。

69

帖子

7

主题

0

精华

专家

F 币
320 元
贡献
224 点
地板
发表于 2014-3-5 09:47:11 | 只看该作者
Felix804665 发表于 2014-3-5 01:41
函数计算的时候,参数的数据类型和精度会影响函数的计算结果,尤其是当作除法的时候,如果分子很大,分母很 ...

因为计算机字长的关系,相差悬殊的数字的算术运算是会有偏差的,但一般规律是采用的kind的精度越高计算结果应该越准确。

11

帖子

0

主题

0

精华

入门

F 币
103 元
贡献
63 点

帅哥勋章爱心勋章

5#
发表于 2014-3-18 16:01:26 | 只看该作者
现在一般都定义双精度了。。。。
您需要登录后才可以回帖 登录 | 极速注册

本版积分规则

捐赠本站|Archiver|关于我们 About Us|小黑屋|Fcode ( 京ICP备18005632-2号 )

GMT+8, 2024-12-24 00:40

Powered by Tencent X3.4

© 2013-2024 Tencent

快速回复 返回顶部 返回列表