12

我正在编写通过 Windows 中的 COM与NI TestStand 4.2 交互的 Python 2.6 代码。我想为变量创建一个“NAN”值,但如果我通过它float('nan'),TestStand 将它显示为IND.

显然,TestStand 区分浮点“IND”和“NAN”值。根据TestStand 帮助

  • IND对应于 Visual C++中的Signaling NaN ,而
  • NAN对应QuietNaN

这意味着当通过 COM 传递Python 时,float('nan')它实际上是一个Signaling NaN 。但是,从我读到的有关Signaling NaN的内容来看, Signaling NaN似乎有点“异国情调”,而Quiet NaN是您的“常规” NaN。所以我怀疑 Python 是否会通过 COM传递Signaling NaN 。我怎样才能知道 Python是否作为Signaling NaNQuiet NaNIndeterminatefloat('nan')通过 COM 传递?

在与其他语言交互时,有没有办法在 Python 中制作Signaling NaNQuietNaNIndeterminate ?ctypes也许使用?)我认为这将是一个特定于平台的解决方案,在这种情况下我会接受。

更新:在 TestStand 序列编辑器中,我尝试制作两个变量,一个设置为NAN,另一个设置为IND. 然后我把它保存到一个文件中。然后我打开文件并使用 Python 读取每个变量。在这两种情况下,Python 都将它们读取为nan浮点数。

4

4 回答 4

9

我为您挖了一点,我认为您可以struct结合Kevin's Summary Charts上的信息使用该模块。他们解释了用于各种 IEEE 754 浮点数的确切位模式。

如果我阅读有关此 -eterminate 值的主题,您可能需要注意的唯一一件事IND是,当直接在 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'

参考Kevin's Summary Charts,这表明这float('nan')在技术上实际上是 Indeterminate 值,scipy.nan而是 Quiet NaN。

让我们尝试制作一个 Signaling 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'

不,Signaling NaN 被转换为 Quiet 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()至少在 Windows 平台上制作正确的 Quiet NaN 的方法。

于 2010-10-08T02:42:22.623 回答
5

nan的CPython定义

当 Python 报告 anan时,它是从哪里来的?

  • 计算结果(平台特定值?)
  • Py_NAN在 CPython C 源代码中
    • 定义为(Py_HUGE_VAL * 0.)
      • 值是特定于平台的
      • Py_HUGE_VAL可能被定义为HUGE_VAL-- 它有一个注释说它应该是HUGE_VAL除了在被破坏的平台上。
  • float('nan')这是Py_NAN在 CPython 的 C 源代码中定义的。

阅读 Python 和 pywin32 源码

我查看了 的 C 源代码pywin32,特别是win32com,它构成了 Python↔COM 转换层。该代码:

  • 接受输入对象
  • PyNumber_Float()将其转换为 Python 的调用float(如果还没有)
  • 调用PyFloat_AsDouble()将其转换为纯 Cdouble值。
    • 这只是返回 Cdouble直接包含在PyFloatObjectmemberob_fval中。

所以看起来我已经将 aNaN从 COM 接口追溯到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 文件,其中变量设置为INDand NAN,并从 Python 读取值。事实证明,TestStand 的NAN值为FFFF000000000001. 根据Kevin 的总结图表,这是一个消极的安静 NAN。TestStand确实具有IndeterminateIND的预期值,。FFF8000000000000

成功

所以,毕竟,我已经成功地从 Python 在 TestStand 中设置了一个 NAN:

# 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)
于 2010-10-11T06:50:09.953 回答
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
于 2010-10-08T02:21:51.670 回答
0

据我所知,认为 a 的符号NaN决定它是否安静似乎有些混乱。相反,惯例是尾数的最高有效位决定了这一点。来自维基百科(强调添加):

在符合 IEEE 754 标准的浮点存储格式中,NaN 由特定于 NaN 的预定义位模式标识。符号位无关紧要。二进制格式 NaN 用填充了 1 的指数字段(如无穷大值)和有效数字字段中的一些非零数表示(以使它们与无穷大值不同)。1985 年的原始 IEEE 754 标准 (IEEE 754-1985) 仅描述了二进制浮点格式,并没有指定如何标记信令/安静状态。在实践中,有效位字段的最高有效位决定了 NaN 是信令还是安静...... IEEE 754 标准 (IEEE 754-2008) 的 2008 年修订版对信令/安静状态的编码提出了正式建议。对于二进制格式,有效位字段的最高有效位应该是“is_quiet”标志。即,如果 NaN 是安静的,则该位非零,如果 NaN 正在发信号,则该位为零

由于大多数实现都符合 IEEE 754-2008,因此这是您应该遵循的约定。通常,您无法计划对 NaN 的符号位保持一致,即使对于同一平台上的不同 NaN 也是如此。在这个约定下,至少在上面讨论的情况下,两者似乎都是安静的 NaN float('nan')scipy.nan

于 2018-10-08T02:54:41.307 回答