Как различать различные типы 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