Согласно документации Python, Python использует функции работы с плавающей запятой того оборудования, на котором он работает а>. На большинстве современных машин это арифметика IEEE-754 или что-то близкое к ней. В этой документации Python явно не указан режим округления, но вскользь упоминается, что результатом выборочного деления является ближайшее представимое значение, поэтому, предположительно, Python использует режим округления до ближайших связей до четности. («Округление до ближайшего» для краткости. Если два представимых значения одинаково близки в двоичном формате с плавающей запятой, создается одно с нулем в младшем бите его мантиссы.)
В арифметике IEEE-754 в режиме округления до ближайшего результатом деления является представимое значение, ближайшее к точному математическому значению. Поскольку вы говорите, что математическое значение x/y
разумно, оно находится в нормальном диапазоне представимых значений (не ниже его, в субнормальном диапазоне, где страдает точность, и не выше него, где результаты округляются до бесконечности). В нормальном диапазоне результаты элементарных операций будут точными в пределах нормальной точности формата.
Однако, поскольку x
и y
являются «очень маленькими числами», мы можем быть обеспокоены тем, что они субнормальны и имеют потерю точности уже в них, прежде чем будет выполнено деление. В базовом 64-битном двоичном формате IEEE-754 числа меньше 2-1022 (около 2,22507•10-308) являются субнормальными. Если x
и y
меньше этого, то они уже потеряли точность, и ни один метод не может получить из них правильное частное, кроме как по чистой случайности. Логарифмирование для вычисления частного не поможет.
Если машина, на которой вы работаете, не использует IEEE-754, вполне вероятно, что прямое вычисление x/y
даст лучший результат, чем np.exp(np.log(x)-np.log(y))
. Первая представляет собой единственную операцию, вычисляющую базовую функцию аппаратного обеспечения, которая, вероятно, была разумно спроектирована. Последний представляет собой несколько операций, вычисляющих сложные функции в программном обеспечении, которые трудно сделать точными, используя обычные аппаратные операции.
Существует изрядное беспокойство и недоверие к операциям с плавающей запятой. Недостаток знаний, кажется, приводит к тому, что люди боятся их. Но здесь следует понимать, что элементарные операции с плавающей запятой очень хорошо определены и точны в нормальных пределах. Реальные проблемы с вычислениями с плавающей запятой возникают из-за накопления ошибок округления в последовательностях операций, из-за присущей математике, которая усугубляет ошибки, и из-за неправильных ожиданий результатов. Это означает, что нет необходимости беспокоиться о точности одного деления. Скорее, следует помнить об общем использовании чисел с плавающей запятой. (На ваш вопрос можно было бы лучше ответить, если бы он представил больше контекста, освещающего, почему это разделение важно, как x
и y
были получены из предыдущих данных и какова общая цель.)
Примечание
Нередким отклонением от IEEE-754 является обнуление ненормальных значений. Если у вас есть некоторые x
и некоторые y
, которые являются субнормальными, некоторые реализации могут сбросить их до нуля перед выполнением над ними операций. Однако это чаще встречается в коде SIMD, чем в обычном скалярном программировании. И, если бы это произошло, это в любом случае помешало бы вам оценить np.log(x)
и np.log(y)
, так как субнормальные значения также были бы сброшены до нуля в них. Так что мы, вероятно, можем отбросить эту возможность.
person
Eric Postpischil
schedule
10.01.2018
x
иy
слишком малы для представления в IEEE с плавающей запятой? - person Mark Ransom   schedule 10.01.2018x/y
не получится, и делалnp.exp(np.log(x) - np.log(y)
, но потом мне стало интересно, имеет ли это какое-то значение. Немного подредактирую вопрос. - person p-value   schedule 10.01.2018log
иexp
дало бы лучший результат, чем прямое деление. Хотя известно, что иногда мне не хватало воображения. - person Mark Ransom   schedule 10.01.2018