如何在Python中区分不同类型的NaN float

Cra*_*een 10 python windows com interop nan

我正在编写Python 2.6代码,通过Windows中的COM 与NI TestStand 4.2连接.我想为变量创建一个"NAN"值,但如果我传递它float('nan'),TestStand 会将其显示为IND.

显然,TestStand区分浮点"IND"和"NAN"值.根据TestStand的帮助:

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

这意味着Python 在通过COM时float('nan')实际上是一个信令NaN.然而,从我读到的有关信号NaN的内容来看,似乎信号NaN有点"异国情调"而Quiet NaN是你的"常规"NaN.所以我怀疑Python会通过COM 传递信令NaN.我怎么能知道Python float('nan')是通过COM作为信令NaN还是Quiet NaN传递,还是可能不确定

在与其他语言连接时,有没有办法在Python中建立信令NaNQuietNaNIndeterminate?(ctypes或许使用?)我认为这将是一个特定于平台的解决方案,在这种情况下我会接受.

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

Sti*_*gma 7

我为你挖了一下,我想你可以将这个struct模块与Kevin的摘要图表中的信息结合使用.它们解释了用于各种IEEE 754浮点数的精确位模式.

如果我阅读关于此IND-eminminate值的主题,那么您可能必须要小心的唯一事情是,当直接在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'
Run Code Online (Sandbox Code Playgroud)

参考Kevin的摘要图表,它显示了float('nan')技术上实际上是Indeterminate值,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'
Run Code Online (Sandbox Code Playgroud)

不,信令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'
Run Code Online (Sandbox Code Playgroud)

这就是如何使用 - struct.unpack()至少在Windows平台上制作适当的Quiet NaN .


Cra*_*een 5

nan 的 CPython 定义

当 Python 报告 a 时nan,它来自哪里?

  • 计算结果(平台特定值?)
  • 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值。
    • 这个简单的返回Çdouble直接包含在PyFloatObject构件ob_fval

所以看起来好像我已经NaN从 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)
Run Code Online (Sandbox Code Playgroud)

但它仍然出现在 TestStand 中IND。然后我创建了一个 TestStand 文件,变量设置为INDand NAN,并从 Python 读取值。事实证明,TestStand 的NAN值为FFFF000000000001。根据凯文的总结图表,这是一个消极的安静 NAN。TestStandIND确实具有Indeterminate的预期值,FFF8000000000000

成功

所以,毕竟,我已经成功地在 TestStand 中从 Python 设置了一个 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)
Run Code Online (Sandbox Code Playgroud)