【问题标题】:Sign of infinity on division by zero除以零时的无穷大符号
【发布时间】:2019-06-18 13:39:17
【问题描述】:

我已经实现了在 2D 空间中查找点的极坐标的代码。如果该点位于第一或第二象限,0<=theta<=pi,如果它位于第三或第四象限,-pi <= theta <= 0

      module thetalib

      contains 
      real function comp_theta( x1, x2)
      implicit none

      real        , intent(in)    :: x1, x2
      real                        :: x1p, x2p
      real                        :: x1_c=0.0, x2_c=0.0
      real                        :: pi=4*atan(1.0)

      x1p = x1 - x1_c
      x2p = x2 - x2_c

!  - Patch
      !if ( x1p == 0 .and. x2p /= 0 ) then
      !   comp_theta = sign(pi/2.0, x2p)
      !else
      !   comp_theta = atan ( x2p / x1p )
      !endif

      comp_theta = atan( x2p / x1p)

      if ( x1p >= 0.0 .and. x2p >= 0.0 ) then
         comp_theta = comp_theta
      elseif ( x1p < 0 .and. x2p >= 0.0 ) then
         comp_theta = pi + comp_theta
      elseif( x1p < 0.0 .and. x2p < 0.0 ) then
         comp_theta = -1* (pi - comp_theta)
      elseif ( x1p >= 0.0 .and. x2p < 0.0 ) then
         comp_theta = comp_theta
      endif

      return
      end function comp_theta

      end module thetalib

      program main

      use thetalib

      implicit none

!     Quadrant 1
      print *, "(0.00, 1.00): ", comp_theta(0.00, 1.00)
      print *, "(1.00, 0.00): ", comp_theta(1.00, 0.00)
      print *, "(1.00, 1.00): ", comp_theta(1.00, 1.00)

!     Quadrant 2
      print *, "(-1.00, 1.00): ", comp_theta(-1.00, 1.00)
      print *, "(-1.00, 0.00): ", comp_theta(-1.00, 0.00)

!     Quadrant 3
      print *, "(-1.00, -1.00): ", comp_theta(-1.00, -1.00)


!     Quadrant 4
      print *, "(0.00, -1.00): ", comp_theta(0.00, -1.00)
      print *, "(1.00, -1.00): ", comp_theta(1.00, -1.00)

      end program main

在函数thetalib::comp_theta 中,当除以零且分子为+ve 时,fortran 将其计算为-infinity,当分子为-ve 时,将其计算为+infinity(参见输出)

 (0.00, 1.00):   -1.570796    
 (1.00, 0.00):   0.0000000E+00
 (1.00, 1.00):   0.7853982    
 (-1.00, 1.00):    2.356194    
 (-1.00, 0.00):    3.141593    
 (-1.00, -1.00):   -2.356194    
 (0.00, -1.00):    1.570796    
 (1.00, -1.00):  -0.7853982  

这让我很困惑。我还实施了您看到的补丁来解决它。为了进一步调查,我设置了一个小测试:

  program main

  implicit none

  real          :: x1, x2

  x1 = 0.0 - 0.0 ! Reflecting the x1p - 0.0
  x2 = 1.0

  write(*,*) "x2/x1=", x2/x1

  x2 = -1.0
  write(*,*) "x2/x1=", x2/x1

  end program main

计算结果为:

 x2/x1=       Infinity
 x2/x1=      -Infinity

我的 fortran 版本:

$ ifort --version
ifort (IFORT) 19.0.1.144 20181018
Copyright (C) 1985-2018 Intel Corporation.  All rights reserved.

我有三个问题:

  1. 为什么会有有符号的无限值?
  2. 标志是如何确定的?
  3. 为什么infinity 使用thetalib::comp_theta 和测试程序的输出中显示的符号?

【问题讨论】:

  • 使用atan2(y,x)函数不是比自己旋转更容易吗?
  • @Steve 是的,对于这种特殊情况,但我想知道为什么标志不匹配。
  • 你是在问为什么会有有符号的无限值,为什么每个都是短测试的结果,或者如何避免它们?
  • @francescalus 是的,(a)为什么有有符号的无限值? (b) 符号是如何确定的——无论是在简短的测试用例中还是在thetalib::comp_theta?如何避免将遵循 (a) 和 (b) 的答案。将编辑问题以反映这一点。
  • @IAmNerd2000 我尝试使用x1 = 0.0 - 0.0 行中的测试程序复制它,但结果不同。限制也是我想到的第一件事,但我无法重现它。

标签: fortran intel-fortran


【解决方案1】:

从支持 IEEE 算术的编译器得出有符号的无限值。

对于动机,考虑真正的非零分子和分母。如果它们的符号相同,则商是实数(有限)正数。如果它们的符号相反,则商是实数(有限)负数。

考虑极限1/x,因为x 从下方趋于零。对于x 的任何严格负值,该值为负。考虑到连续性,极限可以取负无穷。

所以,当分子不为零时,如果分子和分母的符号相同,商将是正无穷大,如果符号相反,商将是负无穷大。还记得,零分母may be signed

如果你想检查这个数字,看看它是否是有限的,你可以使用内部模块ieee_arithmetic 的过程IEEE_IS_FINITE。此外,该模块具有过程IEEE_CLASS,它提供了有关其参数的有用信息。除其他事项外:

  • 是正数还是负数正常数;
  • 是正无穷值还是负无穷值;
  • 是正零还是负零。

【讨论】:

  • 这与@IAmNerd2000 的回答一起澄清了所问问题的所有部分。有没有办法将两者合并?
  • @newkid 现在你明白为什么你应该在这里问每个帖子一个问题。
【解决方案2】:

您也可以尝试检查数字是否等于自身。如果不是那么。它是无限的。

EX:if ( x2x1 .eq. x2x1) 然后是好号码。如果不是那么无穷大。

也可能是保存 x1 的值是由计算机计算的,其中数字中的所有位都设置为 1(-infinity),然后按位除以得到以下结果:

这实际上是一个减法运算,其中 (0....001 - 01...111) = -Infinity 和 (0....001 - 11.....111) = +Infinity 我会查找按位除法并查看相关信息。做的比较多,细节就不用我解释了。

【讨论】:

  • 这解释了部分答案,即测试程序中的输出已经非常好。谢谢!关于函数 comp_theta 中发生的任何想法?
  • 我注意到您的 elseif 语句中有以下 x1p &lt; 0 应该是 x1p &lt; 0.0 否则它会将 x1p 评估为整数
猜你喜欢
  • 1970-01-01
  • 2017-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-11
  • 1970-01-01
  • 2023-04-01
  • 1970-01-01
相关资源
最近更新 更多