Ответ 1
Если вы выполняете любое из следующих действий без обхода среды с плавающей точкой, вы должны получить NaN, где у вас его не было:
-
0/0
(либо знак сверху и снизу) -
inf/inf
(либо знак сверху и снизу) -
inf - inf
или(-inf) + inf
илиinf + (-inf)
или(-inf) - (-inf)
-
0 * inf
иinf * 0
(либо знак обоих факторов) -
sqrt(x)
, когдаx < 0
-
fmod(x, y)
, когдаy = 0
илиx
бесконечно; здесьfmod
является остатком с плавающей запятой.
Каноническая ссылка для этих аспектов машинной арифметики - это спецификация IEEE 754. В разделе 7.1 описано исключение недействительной операции, которое возникает, когда вы собираетесь получить NaN. "Исключение" в IEEE 754 означает нечто иное, чем в контексте языка программирования.
Множество реализаций специальных функций документирует их поведение в особенностях функции, которую они пытаются реализовать. См. Справочную страницу для atan2
и log
, например.
Вы спрашиваете конкретно о NumPy и SciPy. Я не уверен, что это просто сказать: "Я спрашиваю об арифметике машины, которая происходит под капотом в NumPy" или "Я спрашиваю о eig()
и прочее". Я предполагаю, что первый, но остальная часть этого ответа пытается смутно подключиться к функциям более высокого уровня в NumPy. Основное правило: Если реализация функции совершает один из вышеуказанных грехов, вы получаете NaN.
Для fft
, например, вы можете получить NaN
, если ваши входные значения находятся вокруг 1e1010
или больше, и тихая потеря точности, если ваши входные значения находятся вокруг 1e-1010
или меньше. Тем не менее, помимо действительно смехотворно масштабированных входов, вы совершенно безопасны с fft
.
Для вещей, связанных с матричной математикой, NaN могут возникать (обычно через маршрут inf - inf
), если ваши цифры огромны или, ваша матрица крайне плохо обусловлена. Полное обсуждение того, как вы можете ввернуться в числовую линейную алгебру, слишком долго, чтобы принадлежать в ответ. Я бы посоветовал перечислить числовую книгу линейной алгебры (Trefethen и Bau популярен) в течение нескольких месяцев.
Одна вещь, которую я нашел полезной при написании и отладке кода, который "не должен" генерировать NaN, - это указать машине на ловушку, если происходит NaN. В GNU C я делаю это:
#include <fenv.h>
feenableexcept(FE_INVALID);