Как различать различные типы NaN float в Python
я пишу код Python 2.6, который взаимодействует с Ni TestStand 4.2 через COM в Windows. Я хочу сделать значение" NAN " для переменной, но если я передам его float('nan'), TestStand отображает его как IND.
по-видимому, TestStand различает значения с плавающей запятой "IND" и "NAN". Согласно испытательном комплексе помочь:
-
INDсоответствует Сигнализация NaN в Visual C++, в то время как -
NANсоответствует QuietNaN
это означает, что Python float('nan') эффективно Сигнализация NaN при прохождении через COM. Однако из того, что я читал о Сигнализация NaN кажется, что Сигнализация NaN немного "экзотический" и Тихий НАНА ваша "обычная" Нэн. Поэтому у меня есть сомнения, что Python будет проходить Сигнализация NaN через COM. как я мог узнать, если питон float('nan') передается через COM как Сигнализация NaN или Тихий НАНА, а может неопределено?
есть ли способ сделать Сигнализация NaN и QuietNaN или неопределено в Python, при взаимодействии с другими языками? (Используя ctypes возможно?) Я предполагаю, что это будет решение для конкретной платформы, и я бы принял это в этом случай.
обновление: в Редакторе последовательности TestStand я попытался сделать две переменные, одну из которыхNAN и другой набор в IND. Затем я сохранил его в файле. Затем я открыл файл и прочитал каждую переменную с помощью Python. В обоих случаях, Python читает их как nan поплавок.
3 ответов
Я немного покопал для вас, и я думаю, что вы могли бы использовать struct модуль в сочетании с информацией на сводные диаграммы Кевина. Они объясняют точные битовые шаблоны, используемые для различных типов чисел с плавающей запятой IEEE 754.
единственное, что вам, вероятно, придется быть осторожным, если я читаю темы на этом IND-eterminate значение, является то, что это значение имеет тенденцию вызывать какой-то прерывания с плавающей запятой при назначении непосредственно в коде C, заставляя его превращаться в простой NaN. Что, в свою очередь, означало, что этим людям советовали делать такие вещи в ASM, а не C, так как C абстрагировал этот материал.. Поскольку это не моя область, и я не уверен, в какой степени такая ценность будет связываться с Python, я решил упомянуть об этом, чтобы вы могли, по крайней мере, следить за любым таким странным поведением. (См. принятый ответ для этот вопрос).
>>> import struct
>>> struct.pack(">d", float('nan')).encode("hex_codec")
'fff8000000000000'
>>> import scipy
>>> struct.pack(">d", scipy.nan).encode("hex_codec")
'7ff8000000000000'
со ссылкой на Кевин Сводные Диаграммы, это показывает, что float('nan') на самом деле технически неопределенное значение, в то время как scipy.nan тихая Нэн.
давайте попробуем сделать сигнальный NaN, а затем проверить его.
>>> try_signaling_nan = struct.unpack(">d", "\x7f\xf0\x00\x00\x00\x00\x00\x01")[0]
>>> struct.pack(">d", try_signaling_nan).encode("hex_codec")
'7ff8000000000001'
нет, сигнальный NaN преобразуется в Тихий NaN.
теперь давайте попробуем сделать тихий NaN непосредственно, а затем проверить его.
>>> try_quiet_nan = struct.unpack(">d", "\x7f\xf8\x00\x00\x00\x00\x00\x00")[0]
>>> struct.pack(">d", try_quiet_nan).encode("hex_codec")
'7ff8000000000000'
так вот как сделать правильный Тихий NaN с помощью struct.unpack()--по крайней мере, на платформе Windows.
CPython определение nan
когда Python сообщает nan, откуда оно взялось?
- результат расчета (конкретные значения платформы?)
-
Py_NANв исходном коде CPython C- определяется как
(Py_HUGE_VAL * 0.)- значение зависит от платформы
-
Py_HUGE_VAL, вероятно, определяется какHUGE_VAL--у него есть записка, чтобы сказать, что это должно бытьHUGE_VALза исключением платформ, где это сломанный.
- определяется как
-
float('nan')которая определяется изPy_NANв исходном коде C CPython.
чтение исходного кода Python и pywin32
я взглянул на исходный код C для pywin32, в частности win32com, который формирует слой перевода Python COM COM. Этот код:
- принимает входной объект
- звонки
PyNumber_Float()чтобы преобразовать его в Pythonfloat(если это еще не) - звонки
PyFloat_AsDouble()чтобы преобразовать его в простой Cdoubleзначение.- это просто возвращает C
doubleнепосредственно содержится вPyFloatObject.
- это просто возвращает C
таким образом, похоже, что я проследил NaN от com-интерфейса обратно к простому C double тип содержащей Py_NAN, что бы это ни оказалось на платформе Windows.
испытательный стенд NAN Значение
теперь я пробовал это с Ni TestStand. Сначала я попробовал:
quiet_nan = struct.unpack(">d", "\x7f\xf8\x00\x00\x00\x00\x00\x01")[0]
# Set the variable's value in TestStand
locals_prop_object.SetValNumber(var_name, 0, quiet_nan)
но что еще появилось в TestStand как IND. Итак, я создал файл TestStand с переменными, установленными в IND и NAN, и прочитайте значения из Python. Получается, что в испытательном комплексе NAN имеет значение FFFF000000000001. Согласно сводные диаграммы Кевина что это отрицательный спокойной НЭН. Испытательном комплексе по IND имеет ожидаемое значение неопределено, FFF8000000000000.
успехов
Итак, после всего этого мне удалось установить NAN в TestStand, от Python:
# Make a NAN suitable for TestStand
teststand_nan = struct.unpack(">d", "\xff\xff\x00\x00\x00\x00\x00\x01")[0]
# Set the variable's value in TestStand
locals_prop_object.SetValNumber(var_name, 0, teststand_nan)
У Джона Кука был хороший пост на этом, который может быть полезен:
обновление: разве это не сработает?
In [144]: import scipy
In [145]: scipy.nan
Out[145]: 1.#QNAN
In [146]: scipy.inf
Out[146]: 1.#INF
In [147]: scipy.inf * 0
Out[147]: -1.#IND