Dan*_*Bar 0 floating-point fortran rounding-error rounding type-conversion
我正在尝试将双精度数转换为实数以进行某些操作,但我注意到一个错误。我有一个用于读取目的的宏,一个short是 4 个字节,一个long是 8 个字节。
这是执行代码:
print*, x, real(x, kind=short)
print*, x*2.0, real(x*2.0, kind=short)
print*, real( real(x, kind=short), kind=long)
print*, real( real(x*2.0, kind=short), kind=long)
Run Code Online (Sandbox Code Playgroud)
这打印出:
173.43304556187957 173.433044
346.86609112375913 346.866089
173.43304443359375
346.86608886718750
Run Code Online (Sandbox Code Playgroud)
那么首先为什么我在转换为实数后还有任何值然后又返回?难道不应该是这样的吗173.43304400000000?为什么当我转换它们时我的价值观会发生变化?我怎样才能改变这一点?
有关信息,fortran 2003,用 gfortran 编译,但我认为 ifort 也有同样的问题。
谢谢你!
不,不应该。这些值存储为二进制(基数 2)浮点数,双精度的额外小数位是二进制零,而不是十进制零。大多数十进制分数不能完全转换为二进制(反之亦然)。
当您以十六进制格式显示值时,您可以更好地了解发生了什么。我使用了这个程序:
integer, parameter :: short = kind(0.0)
integer, parameter :: long = kind(0.0D0)
real(short) :: r4
real(long) :: r8
r8 = 173.43304556187957_long
print '(G0.16,1X,Z16.16)', r8,r8
r4 = r8
print '(G0.16,1X,Z8.8)',r4, r4
r8 = r4
print '(G0.16,1X,Z16.16)', r8,r8
end
Run Code Online (Sandbox Code Playgroud)
当我运行它时,我得到:
173.4330455618796 4065ADDB825DBE6C
173.4330444335938 432D6EDC
173.4330444335938 4065ADDB80000000
Run Code Online (Sandbox Code Playgroud)
请注意,重新转换为“long”只是添加二进制零,而不更改值。顺便说一句,使用列表定向格式可能会掩盖诸如此类的细节。