【问题标题】:Floating point arithmetic in FortranFortran 中的浮点运算
【发布时间】:2018-11-14 23:46:52
【问题描述】:

我继承了一些我试图理解的 Fortran 代码。它在许多地方使用 REAL 变量,我认为它不应该 - 但也许我误解了它在 Fortran 中的工作原理(与我更熟悉的 C++ 相比),因此这个问题。

因此,所讨论的变量本质上是“分类值”、“因素”或“枚举”,具体取决于您如何看待/想要称呼它。它们的数据类型为 REAL,只能采用有限数量的预定整数值。所以说变量a只能是1、2或3。这些值是从外部文件中读取的;在这些外部文件中,它们表示为整数,因此不是“外部数据源中的舍入问题”之类的情况。

但是在代码中,它从不进行直接比较,总是进行大于/小于检查。所以,而不是做

if (a == 1) then

确实如此

if (a > 0.9 .and. a < 1.1) then

您可以想象这会变得非常混乱/令人厌烦,尤其是当它需要检查一个值是否是多个类别之一时。

所以我认为这是一种情况,有人在某些时候听到“从不比较 REAL 值”(由于存储浮点值的有限精度的性质,每个编程语言都存在同样的问题),但后来没有' 真的不明白什么时候适用(我猜第一个错误是分类值应该表示为整数值,但现在情况就是这样)。

OTOH 也许我只是误解了 REAL 和 INTEGER 值在 Fortran 中是如何表示和工作的?会不会有这样的情况

b = 1.5
a = REAL(INT(b))

if (a > 0.9 .and. a < 1.1) then

有意义吗?

【问题讨论】:

  • 你是对的:“永远不要在没有公差的情况下比较实数。” IEEE 浮点数不能准确。用二进制表示 0.1 不能比用十进制表示 1/3。 FORTRAN 中的实数是 IEEE 浮点数;与整数非常不同。
  • Fortran的实数遵循模型形式s*b^e*\sum_{k=1}^{p}f_k*b^{-k}的一些参数(见here);整数建模类似。
  • 也许我的问题表述不够清楚 - 我的意思是,如果我只将整数值放入实数中,它们可以与 == 进行比较吗?
  • @Roel,是的,您可以使用 ==。如果您有一个 REAL 变量,它可能是一个具有 24 位精度的 32 位实体,因此您可以将相等性与最大为 2^24 的整数值进行比较。如果你有一个 DOUBLE PRECISION 变量,它可能是一个 64 位的 53 位精度的变量。对于 DOUBLE PERCISION,您可以比较高达 2^53 的相等性。为什么?因为这些范围内的整数完全可以用浮点格式表示。
  • 如果变量在逻辑上应该只取一组离散的、预定义的值,那么它绝对应该有一个体现这些限制的类型——至少是整数, 和一个实际的枚举类型(如果 FORTRAN 有它们)。

标签: fortran


【解决方案1】:

只有在您没有对实际值执行任何操作的情况下(只是分配一个值并将相等性与您分配的相同文字、具有相同类型的参数进行比较),您才不需要容忍。

问题是,对于一个实变量 a,例如:

Real a
a = 2

你可以确定

a == 2

将永远是 .true. 。但是例如,对于另一个由 b 表示的实值:

a  / b * b == 2

(或任何其他操作)不保证为.true。

【讨论】:

  • 甚至没有 - 1.0 == 1.0 ?也许我确实误解了浮点表示;除了尾数 1 和指数 0 表示的值之外,它怎么会变成其他任何东西?难道所有(足够小)整数都可以用指数为0的浮点数精确表示,加法和减法也不总是精确的吗? (多年来,我已经多次阅读“关于浮点表示的一切”论文,但我会坦率地承认,我为阅读它的树木而失去了森林)
  • 一般情况下不保证。是的,肯定有一组价值观是正确的,但你不能依赖它:那些价值观是什么?停止工作的门槛是多少?哪些操作(以及使用哪些值)不会破坏它?如何在编译时或运行时检查它?
  • 即使2 无法表示,人们仍然希望real :: a=2; print *, a==2; end 给出真值:同样的转换适用于分配作为测试。
  • 是的,我认为你是对的,@francescalus。我可以撤消我的编辑。我会提出这样的问题:可以对实数值执行哪些操作(以及使用哪些操作数),结果的表示肯定等于预期整数结果到实数的转换?
  • @Roel 所以,你应用了这个建议吗?这个答案对你有帮助吗?如果是,您可以将此标记为“已接受”,以便其他有相同问题的人更容易找到解决方案。
【解决方案2】:

如果由于某种原因变量必须保持真实,那么您可以使用 比较中的固有 Fortran 函数 NINT(最近整数):

if( nint(a) == 1 ) then 
....

【讨论】:

    猜你喜欢
    • 2016-08-23
    • 2018-06-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-10-18
    • 2014-01-24
    相关资源
    最近更新 更多