我正在编写Python 2.6代码,通过Windows中的COM与NI TestStand 4.2进行交互。我想为变量设置“NAN”值,但如果我将其传递给float('nan')
,则TestStand会将其显示为IND
。
显然,TestStand区分浮点“IND”和“NAN”值。根据{{3}}:
IND
对应于Visual C ++中的 Signaling NaN ,而NAN
对应 QuietNaN 这意味着Python的float('nan')
在通过COM时实际上是信令NaN 。但是,从我读到的关于信令NaN 的内容来看,似乎信令NaN 有点“异国情调”而 Quiet NaN 就是你的“定期“NaN。所以我怀疑Python会通过COM传递一个 Signaling NaN 。 如何判断Python float('nan')
是否作为信令NaN 或安静的NaN 传递给COM,或者 Indeterminate 吗
在与其他语言连接时,有没有办法在Python中制作信令NaN 与 QuietNaN 或 Indeterminate ? (也许使用ctypes
?)我认为这将是一个特定于平台的解决方案,在这种情况下我会接受。
更新:在TestStand序列编辑器中,我尝试制作两个变量,一个设置为NAN
,另一个设置为IND
。然后我把它保存到一个文件中。然后我打开文件并使用Python读取每个变量。在这两种情况下,Python都将它们读作nan
float。
答案 0 :(得分:7)
我为你挖了一下,我想你可以将struct
模块与Kevin's Summary Charts上的信息结合使用。它们解释了用于各种IEEE 754浮点数的确切位模式。
如果我阅读关于此IND
- eterminate值的主题,那么您可能必须要小心的是,当直接在C代码中分配时,该值往往会触发某种浮点中断,使它变成普通的NaN。这反过来意味着那些人被建议在ASM而不是C中做这种事情,因为C抽象了那些东西。因为它不是我的领域,而且我不确定这种价值会在多大程度上混乱Python,我想我会提到它,所以你至少可以留意任何这种奇怪的行为。 (参见this question的接受答案)。
>>> import struct
>>> struct.pack(">d", float('nan')).encode("hex_codec")
'fff8000000000000'
>>> import scipy
>>> struct.pack(">d", scipy.nan).encode("hex_codec")
'7ff8000000000000'
参考Kevin's Summary Charts,表明float('nan')
实际上在技术上是不确定的值,而scipy.nan
是一个安静的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。
现在让我们尝试直接制作一个Quiet 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'
这就是如何使用struct.unpack()
制作适当的静音NaN - 至少在Windows平台上。
答案 1 :(得分:3)
CPython对nan的定义
当Python报告nan
时,它来自哪里?
Py_NAN
(Py_HUGE_VAL * 0.)
Py_HUGE_VAL
可能被定义为HUGE_VAL
- 它有一个说明,它应该是HUGE_VAL
,除非在那些被破坏的平台上。float('nan')
,它是在CPython的C源代码中从Py_NAN
定义的。阅读Python和pywin32源代码
我已经查看了pywin32
的C源代码,特别是win32com
,它构成了Python↔COM转换层。那段代码:
PyNumber_Float()
将其转换为Python float
(如果还没有)PyFloat_AsDouble()
将其转换为普通的C double
值。
double
成员PyFloatObject
中直接包含的C ob_fval
。所以看起来我已经从COM接口追溯到NaN
回到包含double
的普通C Py_NAN
类型,无论结果是什么原因都在Windows平台上
TestStand 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)
但是,它仍然作为IND
出现在TestStand中。然后我创建了一个TestStand文件,其变量设置为IND
和NAN
,并从Python中读取值。事实证明,TestStand的NAN
的值为FFFF000000000001
。根据{{3}},否定安静NAN。 TestStand的IND
确实具有 Indeterminate ,FFF8000000000000
的预期值。
<强>成功强>
所以,毕竟,我已经成功地在Python中设置了一个NAN的TestStand:
# 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)
答案 2 :(得分:2)
约翰库克有一个很好的帖子,可能会有所帮助:
更新:这不会有效吗?
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
答案 3 :(得分:0)
据我所知,似乎似乎有些困惑,认为fetch
的符号决定了它是否安静。相反,惯例是尾数的最高有效位决定了这一点。来自Wikipedia(添加了重点):
在符合IEEE 754标准的浮点存储格式中,NaN由NaN唯一的特定预定义位模式标识。 符号位无关紧要。二进制格式的NaNs用填充有1的指数字段(如无穷大值)和有效字段中的一些非零数字表示(以使其与无穷大值不同)来表示。 1985年的原始IEEE 754标准(IEEE 754-1985)仅描述了二进制浮点格式,没有指定如何标记信令/安静状态。实际上,有效字段的最高有效位确定NaN是在发信号还是在静默... 2008年修订的IEEE 754标准(IEEE 754-2008)提出了对信号/安静状态编码的正式建议。 对于二进制格式,significand字段的最高有效位应为'is_quiet'标志。即如果NaN安静,则此位为非零;如果NaN正在发信号,则该位为非零。
由于大多数实现都符合IEEE 754-2008,因此这是您应遵循的约定。通常,您不能计划符号位与NaN保持一致,即使同一平台上的不同NaN也是如此。根据此约定,NaN
和float('nan')
似乎都是安静的NaN,至少在上述情况下如此。