Fortran浮点数相等 [英] Fortran floating point equality
问题描述
我有一个Fortran程序,用于测试两个浮点数的相等性.可以将其浓缩为如下所示.当使用命令行参数"0.1"运行该程序时,我希望它显示期望值",但会显示奇怪".我知道这可能是由于浮点舍入问题引起的,但是我希望有人可以确切解释我应该如何更改inputvariable
,以使该代码使用0.1
命令行参数打印为我所期望的"
I have a Fortran program that tests equality in two floating point numbers. It can be condensed to what is shown below. When this program is run with "0.1" given as a command line argument, I expect it to print "what I expected" but instead it prints "strange". I understand that this is probably due to a floating point rounding issue, but am hoping someone might be able to explain exactly how I should change inputvariable
to make this code print "what I expected" with a command line argument of 0.1
program equalitytest
character(len=3) :: arg1
real*8 :: inputvariable
CALL GET_COMMAND_ARGUMENT(1,arg1)
READ(arg1,*) inputvariable
IF (inputvariable.EQ.0.1) THEN
PRINT*, "what I expected"
ELSE
PRINT*, "strange"
ENDIF
end program equalitytest
运行如下:
./equalitytest 0.1
strange
推荐答案
从总体上讲,应该很少有理由将相等与实数进行比较.如果我发现自己正在编写这样的代码,我会停下来思考一下我要实现的目标.实际情况是什么反映了这一点?
As a general point, there should be very few reasons why one should need to compare equality with real numbers. If I ever find myself writing such code, I tend to pause and have a think about what I am trying to achieve. What real-world condition is actually a reflection of this?
上述异常与零相关,在编写健壮的代码来检查并处理可能的除以零的情况时,或者在寻找方程的收敛解的情况下,零都属于零-在后一种情况下,应考虑使用零反正三角洲.
The exception to the above relate to zeros, either when writing robust code which checks for and handles possible divisions by zero, or for cases searching for a convergent solution to an equation - in the latter case, this should be considered using a delta anyway.
如果确实需要进行此检查,为什么不将其外包给项目中的标准库,例如
If there really is a need for this check, why not outsource it to a standard library within the project, e.g.
module mylib
use iso_fortran_env
implicit none
private
public :: isReal4EqualReal4
public :: isReal4EqualReal8
public :: isReal8EqualReal4
public :: isReal8EqualReal8
real(real32), parameter :: delta4 = 0.001
real(real64), parameter :: delta8 = 0.0000000001
contains
logical function isReal4EqualReal4(lhs, rhs) result(equal)
real(real32), intent(in) :: lhs
real(real32), intent(in) :: rhs
equal = (abs(lhs - rhs) .le. delta4)
end function isReal4EqualReal4
logical function isReal4EqualReal8(lhs, rhs) result(equal)
real(real32), intent(in) :: lhs
real(real64), intent(in) :: rhs
equal = (abs(lhs - real(rhs,4)) .le. delta4)
end function isReal4EqualReal8
logical function isReal8EqualReal4(lhs, rhs) result(equal)
real(real64), intent(in) :: lhs
real(real32), intent(in) :: rhs
equal = isReal4EqualReal8(rhs, lhs)
end function isReal8EqualReal4
logical function isReal8EqualReal8(lhs, rhs) result(equal)
real(real64), intent(in) :: lhs
real(real64), intent(in) :: rhs
equal = (dabs(lhs - rhs) .le. delta8)
end function isReal8EqualReal8
end module mylib
忘了补充一点,上面的好处之一是,如果我试图在使用错误的接口时比较两个不同类型的实数,则编译器会警告我
Forgot to add that one of the benefits of the above is the compiler will warn me if I'm attempting to compare two real numbers of different types while using the wrong interface
已更新为使用可移植的实数定义.
Updated to use portable real number definitions.
这篇关于Fortran浮点数相等的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!