Почему при вычислении знака произведения двух переменных используется абсолютное значение?
Модуль библиотеки Netlib для функции поиска корней Brent проверяет, что знаки двух переменных различаются следующим образом:
if (fa * (fb/dabs(fb)) .le. 0.0d0) go to 20
...
Почему эта проверка должна включать
/dabs(fb)
вместо того, чтобы быть просто
(fa*fb) .le. 0.0d0
? Я быстро проверил Python, и кажется, что для очень больших значений (+/-1e200) для x и y, где x*y=+/- inf, сравнение x*y<= 0 по-прежнему работает правильно.
1 ответ
Фортран никогда не указывал такую функцию, как
signs_differ(x,y)
, поэтому обычно это делается лично.
x*y<0
(и
x*y.lt.0
) не спрашивает то же самое, что "имеют ли x и y разные знаки?". В то время как произведение x и y, являющееся положительным, означает, что x и y имеют один и тот же знак в (математических) действительных числах, это неверно для (вычислительных) чисел с плавающей запятой.
Умножение с плавающей запятой
x*y
может переполниться, привести к бесконечному значению со знаком (поднятию флага IEEE), при этом сравнение возвращает ожидаемое логическое значение, но это не всегда верно. Было много систем, не относящихся к IEEE, и системы IEEE могут видеть, что этот флаг поднимается и прерывается (или имеют какое-то дорогостоящее отвлечение обработки). Это совсем не то же самое, что "имеют ли x и y один и тот же знак?".
x*(y/dabs(y))
не переполняется, является портативным и потенциально дешевле, чем
(x/dabs(x))*(y/dabs(y))
- игнорирование проблем, связанных с
dabs()
и подписанные нули.
Современный Фортран имеет такие функции, как
sign
,
ieee_copy_sign
и
ieee_signbit
которого не было 40 лет назад.