回 帖 发 新 帖 刷新版面

主题:Fortran精度问题

用以下程序计算tent map时间序列,结果大家可以看到迭代十几步之后精度的误差就这么大,完全偏离预期结果,不知道要怎么办,求解!!!!
program tent 
implicit none
   parameter N=1000
   integer :: i
   double precision :: x(N) 
   open(10,file='data.txt')
    x(1)=0.2_8    
    do i=2,N
      x(i)=1.0-2.0*abs(x(i-1)-0.5)
    end do
    do i=1,N
      write(10,*)i,x(i)
    enddo
end

结果:
           1  0.200000000000000     
           2  0.400000000000000     
           3  0.800000000000000     
           4  0.400000000000000     
           5  0.800000000000000     
           6  0.400000000000000     
           7  0.800000000000001     
           8  0.399999999999999     
           9  0.799999999999997     
          10  0.400000000000006     
          11  0.800000000000011     
          12  0.399999999999977     
          13  0.799999999999955     
          14  0.400000000000091     
          15  0.800000000000182
PS:编译环境用的是CVF6.6

回复列表 (共16个回复)

沙发

x(i)=1.0_8-2.0_8*abs(x(i-1)-0.5_8)
这样会不会好一些?

不过如果遵守规范的话, 1.0, 2.0, 0.5转换成双精度应该没有问题.

看楼主的结果应该就是截断误差的累加. 每次循环都乘以2.

板凳

[quote]x(i)=1.0_8-2.0_8*abs(x(i-1)-0.5_8)
这样会不会好一些?[/quote]
试过了,结果还是那样!

3 楼

先问楼主一个问题, 这个程序的目的是不是用来测量截断误差的?

4 楼

[quote]先问楼主一个问题, 这个程序的目的是不是用来测量截断误差的?[/quote]
当然不是,用来生成一个时间序列的,也就是x(N)

5 楼

分析了一下, 截断误差是由初值x(1)=0.2_8引入的. 后面的算法怎么调整也没用.

把后面输出部分用格式化
write(10,*)i,x(i) => write(10,fmt="(I5,F23.18)")i,x(i)
你会发现二进制浮点数表示无法精确表示0.2, 当2.0*累计到一定程度就出现你所说的精度问题.

这个与语言无关, 不是fortran的问题.

6 楼

[quote]分析了一下, 截断误差是由初值x(1)=0.2_8引入的. 后面的算法怎么调整也没用.

把后面输出部分用格式化
write(10,*)i,x(i) => write(10,fmt="(I5,F23.18)")i,x(i)
你会发现二进制浮点数表示无法精确表示0.2, 当2.0*累计到一定程度就出现你所说的精度问题.

这个与语言无关, 不是fortran的问题.[/quote]
受教了,十分感谢,那么可有办法让我进行迭代之后使截断误差不影响我的结果,迭代十几次就有这么大的误差接受不了!

7 楼

我不懂这个时间序列怎样才算是对的.
我是想算法可不可以反过来, 从你序列最终终止的1.0开始反过来算出每个时序的数? 而不是随手设定的一个例如0.2这样的常数?

8 楼

[quote]我不懂这个时间序列怎样才算是对的.
我是想算法可不可以反过来, 从你序列最终终止的1.0开始反过来算出每个时序的数? 而不是随手设定的一个例如0.2这样的常数?[/quote]
如果是精确的迭代的话,应该一直是0.8和0.4两个值一个周期序列,结果由于误差的影响使序列最终稳定在0.0了(60个点之后的值全为0.0),这个结果严重影响最终结论啊,搞得我很受伤啊。。。。

9 楼

[quote]我不懂这个时间序列怎样才算是对的.
我是想算法可不可以反过来, 从你序列最终终止的1.0开始反过来算出每个时序的数? 而不是随手设定的一个例如0.2这样的常数?[/quote]
计算机只有计算整型是绝对精确的。
如果你需要精确计算,那么不要使用浮点数,请全部使用整型。
然后再把结果除以一个倍数就是你要的结果。
先明白理论解、数值解、误差限之间的关系。

10 楼

这样误差是最小的

program tent
implicit none
   integer,parameter :: N=1000
   integer :: i
   integer :: x(N)
   open(10,file='data.txt')
    x(1)=2
    do i=2,N
      x(i)=10-2*abs(x(i-1)-5)
    end do
    do i=1,N
      write(10,*)i,x(i)/10._8
    enddo
end

当然也可以输出精确解,以字符串之类的方式构造类型,可以参考各种高精度算法。

我来回复

您尚未登录,请登录后再回复。点此登录或注册