回 帖 发 新 帖 刷新版面

主题:[讨论]求教一个双精度的问题

输入如下

 real*8:: A=1.0d-11

输出A的值为 9.999999999999999E-012,这不是A的真实值

A的真实值是  1.000000000000000E-011

如果运行
real*8:: dt=0.1d-12
real*8 A

A=100*dt
输出的A值就是  1.000000000000000E-011

回复列表 (共15个回复)

沙发


你什么编译器?
我用cvf6.6 输出分别是9.999999999999999E-012  9.999999824516700E-012

板凳


运算越多,累计误差越大,不应该出现你这种情况。

3 楼

我的编译器是vs2008 + ivf

程序里只有这一个语句,没有其他的运算,不存在误差累积

在另一台电脑上vs2003+ivf, 结果还是一样

4 楼


我也用ivf编译了,结果和cvf6.6输出一样!都是9.999999999999999E-012  9.999999824516700E-012,真是怪事,不知道其他网友结果是否一致?

代码如下:
    PROGRAM main 
    
    implicit none
    integer(KIND=2),parameter::K=8
    real(KIND=K)::a=1.0d-11,b
    real(KIND=K)::dt=0.1e-12
    b=100*dt
    write(*,*) a,b
    
    END

5 楼

我又用gfortran 试了一下
代码:

program test
implicit none
real*8:: dt=0.1d-12, b=1.0d-11, A
A=100*dt
write(*,*)b
write(*,*)A
end

结果
9.999999999999999E-012
1.000000000000000E-011

还是一样的,不会是我电脑的问题吧?

6 楼

[quote]
我也用ivf编译了,结果和cvf6.6输出一样!都是9.999999999999999E-012  9.999999824516700E-012,真是怪事,不知道其他网友结果是否一致?

代码如下:
    PROGRAM main 
    
    implicit none
    integer(KIND=2),parameter::K=8
    real(KIND=K)::a=1.0d-11,b
    real(KIND=K)::dt=0.1e-12
    b=100*dt
    write(*,*) a,b
    
    END
[/quote]
你的b的值不对是因为你的dt=0.1e-12 是单精度的,应该是dt=0.1d-12,这样b的结果就是1.000000000000000E-011。

7 楼


我晕,你最初给的是dt=0.1e-12,现在又改成dt=0.1d-12!

改成
    PROGRAM main 
    
    implicit none
    integer(KIND=2),parameter::K=8
    real(KIND=K)::a=1.0d-11,b
    real(KIND=K)::dt=0.1d-12
    b=100*dt
    write(*,*) a,b
    
    END
得到与你一致的结果:9.999999999999999E-012  1.000000000000000E-011

8 楼

应该是浮点数的二进制表示问题
不妨改成4倍精度的数来看一下,比较只输出16位有效数字和默认有效位的结果差异,或许能看出其中的玄机。
    
    PROGRAM main 
    
    implicit none
    integer(KIND=2),parameter::K=16
    real(KIND=K)::a=1.0d-11,b,c=100.,dt=0.1d-12
    b=c*dt
    write(*,'((e30.16))') a,b,c,dt
    write(*,*) a,b,c,dt
    
    END
    
    END

9 楼

[quote]应该是浮点数的二进制表示问题
不妨改成4倍精度的数来看一下,比较只输出16位有效数字和默认有效位的结果差异,或许能看出其中的玄机。
    
    PROGRAM main 
    
    implicit none
    integer(KIND=2),parameter::K=16
    real(KIND=K)::a=1.0d-11,b,c=100.,dt=0.1d-12
    b=c*dt
    write(*,'((e30.16))') a,b,c,dt
    write(*,*) a,b,c,dt
    
    END
    
    END[/quote]

按照这个试了一下,还是无法输出a的准确值。

10 楼

[quote][quote]应该是浮点数的二进制表示问题
不妨改成4倍精度的数来看一下,比较只输出16位有效数字和默认有效位的结果差异,或许能看出其中的玄机。
    
    PROGRAM main 
    
    implicit none
    integer(KIND=2),parameter::K=16
    real(KIND=K)::a=1.0d-11,b,c=100.,dt=0.1d-12
    b=c*dt
    write(*,'((e30.16))') a,b,c,dt
    write(*,*) a,b,c,dt
    
    END
    
    END[/quote]

按照这个试了一下,还是无法输出a的准确值。
[/quote]

a的准确值就那么重要吗?既然用浮点数了,就应该预计到可能存在的舍入误差

我来回复

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