2014-02-05 12 views
7

ЯвляетсяВозможно иметь `` а <Ь, а не (а - Ь <0) `` с поплавками

a < b and not(a - b < 0)

возможно с плавающей точкой в ​​связи с плавающей запятой раунд ошибки? Есть ли пример?

+0

У меня нет определенного ответа, но я собираюсь догадаться, абсолютно. Я считаю, что это зависит от единицы с плавающей точкой машины, на которой запущен Python. –

+2

Как странно, как математика с плавающей запятой, я собираюсь выйти на конечность и сказать «Нет», это невозможно. – mhlester

+2

Если поплавками являются бинарные поплавки IEEE 754, денормализация должна предотвращать это условие. –

ответ

9

Это зависит от формата с плавающей запятой и, в частности, имеет ли он gradual underflow. Бинарная с плавающей запятой IEEE 754. Это означает, что разрыв между двумя отдельными поплавками всегда отличен от нуля, даже если он может быть представлен только одним значительным битом в крайнем случае.

Наименьшая возможная абсолютная разница между двумя отдельными поплавками имеет знак равенства (или одно из чисел 0), нулевой показатель и значения, отличающиеся на 1. В этом случае вычитание большего из меньшего приведет к наименьшее отрицательное число величины, с отрицательным знаком, нулевой показатель и значение 1. Это число сравнивается меньше нуля.

Существуют другие расчеты, которые выполняют нижнее значение до нуля. Например, деление наименьшего положительного числа на число, большее или равное двум, приводит к нулю в нормальном режиме округления.

+0

Что означает OP, означает 'a < b' and 'a > b'. Потому что 'not (a - b <0)' должен быть 'a> b'. Даже с ошибками округления и ссылкой wiki @ PatriciaShanahan, 'a-b' может быть округлено до 0, если разница меньше наименьшего числа, которое может быть представлено float. Но 'a < b and a > b' состояние кажется невозможным. – FallenAngel

+0

Как проверить, какой формат с плавающей запятой есть? Я запускаю Ubuntu 12.04 с процессором i7-3520M – SlimJim

+0

если IEEE754 => возможно (или нет?) – SlimJim

0

Вы можете запустить через некоторые из «угловых случаев» легко, как этот

>>> from itertools import product 
>>> for a, b in product([0.0, 1.0, float('-inf'), float('inf'), float('nan')], repeat=2): 
...  print a < b and not(a - b < 0)... 
False 
False 
# and so on 
+0

Существует гораздо больше угловых случаев, таких как ± FLT_MIN и ± FLT_MAX, субнормальные числа, отрицательный ноль и т. Д. Это также далека от строгих. Положительный результат был бы неоспоримым, но отрицательные результаты мало что значили. –

+0

@JohnKugelman, Да. поэтому я старался использовать такие слова, как «некоторые» и «как». Очевидно, что добавить список тестов в список легко. Также довольно очевидно, что это не всеобъемлющий тест. –

9

[Этот ответ предназначен как дополнение педанта к тонкому ответу уже дали Патрисию Shanahan. Этот ответ охватывает нормальный случай; здесь мы беспокоимся о краях, которые вряд ли встречаются на практике.]

Да, это вполне возможно. Вот сессия Python с моим очень обычным, Intel на основе Mac ноутбука:

Enthought Canopy Python 2.7.6 | 64-bit | (default, Jan 29 2014, 17:09:48) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import evil 
>>> a = float.fromhex('1p-1022') 
>>> b = float.fromhex('1.01p-1022') 
>>> a < b and not(a - b < 0) 
True 

Конечно, как импорт показывает, что есть что-то зло здесь происходит. Вот содержимое evil.py. (Предупреждение: это очень специфично для платформы, и, как написано, будет работать только на OS X. Вариации этого должны работать на Linux/x64 при условии, что Python был скомпилирован для использования инструкций SSE2 вместо блока x87 для операций с плавающей запятой . Я понятия не имею о Windows.)

# Being lazy: we should really import just the things we need. 
from ctypes import * 

# Type corresponding to fenv_t from fenv.h. (Platform specific!) 
class fenv_t(Structure): 
    _fields_ = [("control", c_ushort), ("status", c_ushort), 
       ("mxcsr", c_uint), ("reserved", c_char * 8)] 

# Wrap fegetenv and fesetenv from the C library. 
libc = CDLL("/usr/lib/libc.dylib") 
fegetenv = libc.fegetenv 
fegetenv.restype, fegetenv.argtypes = c_int, (POINTER(fenv_t),) 
fesetenv = libc.fesetenv 
fesetenv.restype, fesetenv.argtypes = c_int, (POINTER(fenv_t),) 

# Set the flush-to-zero (FTZ) bit in the MXCSR control register. 
env = fenv_t() 
fegetenv(pointer(env)) 
env.mxcsr |= 1 << 15 
fesetenv(pointer(env)) 

Так что мы делаем здесь, баловаться с настройками ФПУ, проведенных в регистре управления MXCSR. На процессорах Intel 64, поддерживающих наборы инструкций SSE, есть два интересных флага, которые влияют на поведение операций с субнормальными числами. Флаг FTZ (flush-to-zero), когда он установлен, вызывает какой-либо субнормальный вывод арифметической операции, подлежащей замене на ноль. Флаг DAZ (denormals-is-zero), когда он установлен, вызывает любой субнормальный вход в арифметическую операцию, которая должна обрабатываться так, как если бы она была равна нулю. Суть этих флагов заключается в том, что они могут значительно ускорить операции с субнормальными числами за счет снижения соответствия стандарту IEEE 754. В приведенном выше коде мы установили флаг FTZ в регистр управления MXCSR.

И теперь мы выбираем a и b так, что оба a и b являются нормальными, но их разность субнормальна. Тогда a < b будет правдой (как обычно), но a - b будет -0.0, а сравнение a - b < 0 не удастся.

Точка вылета заключается в том, что недостаточно того, что формат с плавающей запятой вы используете формат IEEE 754. Вам также необходимо знать, что ваши действия соответствуют стандарту. Режим FTZ является примером того, как это может произойти. Чтобы связать это с ответом Патрисии Шанахан: код в evil.py отключает постепенное переполнение, которое обещает IEEE 754. (Спасибо @EricPostpischil за указание на это в комментариях.)

+0

Чтобы извлечь ключевой момент для читателей: код в 'evil.py' отключает * постепенное переполнение *, что [ответ Патрисии Шанахан] (http://stackoverflow.com/a/21591038/298225) говорит, что это гарантирует хорошее поведение , Существуют платформы, где это плохое поведение по умолчанию. –

+0

@EricPostpischil: Спасибо; Я впитал некоторые ваши комментарии в ответ. –

Смежные вопросы