在对齐实际值时避免舍入问题

时间:2013-10-16 19:10:42

标签: floating-point fortran

我想反复增加我的变量time,并确保它与所有align_time的倍数精确匹配。

目前我有一个功能

subroutine align(time, incr, align_time)
  real(8) time, incr, align_time

  if (modulo(time+incr,align_time) .lt. modulo(time,align_time)) then
      incr = align_time - modulo(time,align_time)
  end if

  time = time + incr
end subroutine

可以像

一样调用
time = 0
align_time = 100
do while (time < 10000) 
    incr = cpt_incr(...)
    call align(time, incr, align_time) 
    ...
end do

问题在于由于舍入错误,程序会在某个时刻挂起。 假设align_time为0.1,time等于0.6-eps(eps为机器epsilon),当它应为0.6时,则incr始终设为0。

我还应该提到align_time可能会在某些时候发生变化,例如if (time > 1000) align_time = 200

有人知道如何以一种免于舍入错误的方式解决问题吗?

[我对标签和标题没有任何好的想法,如果你这样做,请编辑。此外,不想添加Fortran,因为同样应该适用于C或其他]

编辑: 必须降低incr的值才能实现对齐,从不增加。 align_time可以比incr值大100倍,但也可以更小。 incr不是一成不变的。

1 个答案:

答案 0 :(得分:0)

添加integer(8) itime = 0time_mult = huge(itime)/2/time_end后 在我的初始化中,我将子程序改为:

subroutine align(time, incr, align_time)
    real(8) time, incr, align_time
    integer(8) iincr, ialign

    iincr = nint(incr*time_mult, 8)
    ialign = nint(align_time*time_mult, 8)
    if (modulo(itime+idt,ialign) .lt. modulo(itime,ialign)) then
        iincr = ialign - modulo(itime,ialign)
    end if

    itime = itime + idt

    time = itime/time_mult
    incr = iincr/time_mult
end subroutine

一切似乎都有效。

致信@KyleKanos,他指出了我的方向。