如何解决带符号零的问题?

How to resolve the issue with signed zero?

我现在才知道 'signed zeroes',因为我正在尝试处理复数。问题是:

PROGRAM sZ
       IMPLICIT NONE
       REAL(KIND(0.d0)),PARAMETER :: r=0.2
       COMPLEX(KIND(0.d0)) :: c0
       c0=(0.0,0.5); print*,sqrt(c0**2-r)
       c0=(-0.0,0.5); print*,sqrt(c0**2-r)
       END PROGRAM sZ

虚部符号改变。

(0.0000000000000000,0.67082039547127081)
(0.0000000000000000,-0.67082039547127081)

非常欢迎任何 instructions/suggestions 解决此问题。

你可以做这样的事情,所以一个带符号的(负)零被捕获并替换为零。

PROGRAM sZ
      IMPLICIT NONE

      REAL(KIND(0.d0)),PARAMETER :: r=0.2
      COMPLEX(KIND(0.d0)) :: c0

      REAL(KIND(0.d0)),PARAMETER :: i = -0.0
      REAL(KIND(0.d0)),PARAMETER :: j = 0.5
      REAL(KIND(0.d0)),PARAMETER :: zero = 0.0

      if (i .EQ. 0) then
              c0 = (zero, j); print*,sqrt(c0**2-r)
      else
              c0=(i, j); print*,sqrt(c0**2-r)
      end if

END PROGRAM sZ

我设计了一个小技巧来删除这个 signed zeros

PROGRAM sZ
       IMPLICIT NONE
       REAL(KIND(0.d0)),PARAMETER :: r=0.2
       COMPLEX(KIND(0.d0)) :: c0,zero

       zero=(0.0,0.0)
       c0=(0.0,0.5); c0=c0+zero; print*,sqrt(c0**2-r)
       c0=(-0.0,0.5); c0=c0+zero; print*,sqrt(c0**2-r)

       END PROGRAM sZ

现在结果是一样的。 :)

不过,我想了解更多。什么时候需要符号零

您看到的值来自中间步骤和 sqrt 内在规范。

最终结果取决于 sqrt 的参数值:因为结果有实部和结果虚部的符号

两个参数的虚部符号是什么? (0.,0.5)(-0.,0.5) 平方的虚部在第一种情况下为正,在第二种情况下为负(预期实现有符号零)。减去实数不会影响对象虚部的符号,它成为 sqrt.

的参数

在某种程度上,您得到的结果是正确的,因此唯一需要解决的问题是您对获得相同结果的期望。但是,考虑

  implicit none

  complex :: z1=(-1.,0.), z2=(-1.,-0.)

  print*, z1==z2, SQRT(z1)==SQRT(z2)
end program

即使是正确的,也很容易看出为什么会造成混淆。如果我们不希望这种情况发生,我们可以强制任何零虚部为一个特定符号(例如,非负):

! Force imaginary part away from -0.
if (z%Im==0.) z%Im = 0.

(这个评论很有必要。)

我们可以使用 z%Im 指示符访问和设置复变量的虚部,但这对于一般表达式是不可能的。您可能想要创建一个更通用的函数:

  implicit none

  complex :: z1=(-1.,0.), z2=(-1.,-0.)

  print*, z1==z2, SQRT(z1)==SQRT(z2)
  print*, z1==z2, SQRT(design_0imag(z1))==SQRT(design_0imag(z2))

contains

  pure complex function design_0imag(z) result(zp)
    complex, intent(in) :: z
    zp = z
    if (zp%Im==0.) zp%Im = 0.
  end function design_0imag

end program

如其他答案所示,有几种方法可以实现将 -0 替换为 0 的逻辑(保持其他值不变)。请记住,只有当结果纯属虚构时,您才会体验到这一点。