Python中如何区分不同类型的NaN浮点数
我正在编写 Python 2.6 代码,通过 Windows 中的 COM 与 NI TestStand 4.2 交互。我想为变量创建一个“NAN”值,但如果我传递float('nan')
,TestStand会将其显示为IND
。
显然,TestStand 区分浮点“IND”和“NAN”值。根据 TestStand 帮助:
- < code>IND 对应于 Visual C++ 中的 Signaling NaN,而
NAN
对应于 QuietNaN
这意味着 Python 的 float(当通过 COM 传递时,'nan')
实际上是一个Signaling NaN。然而,从我读到的有关Signaling NaN的内容来看,Signaling NaN似乎有点“异国情调”,而Quiet NaN才是你的“常规”NaN。所以我怀疑 Python 是否会通过 COM 传递Signaling NaN。 如何确定 Python float('nan')
是否作为 Signaling NaN 或 Quiet NaN 通过 COM 传递,或者可能不确定?
有什么办法可以使Signaling NaN与QuietNaN或不确定在Python 与其他语言交互时? (也许使用ctypes
?)我认为这将是一个特定于平台的解决方案,在这种情况下我会接受这一点。
更新:在TestStand序列编辑器中,我尝试创建两个变量,一个设置为NAN
,另一个设置为IND
。然后我把它保存到一个文件中。然后我打开该文件并使用 Python 读取每个变量。在这两种情况下,Python 将它们读取为 nan
浮点数。
I'm writing Python 2.6 code that interfaces with NI TestStand 4.2 via COM in Windows. I want to make a "NAN" value for a variable, but if I pass it float('nan')
, TestStand displays it as IND
.
Apparently TestStand distinguishes between floating point "IND" and "NAN" values. According to TestStand help:
IND
corresponds to Signaling NaN in Visual C++, whileNAN
corresponds to QuietNaN
That implies that Python's float('nan')
is effectively a Signaling NaN when passed through COM. However, from what I've read about Signaling NaN, it seems that Signaling NaN is a bit "exotic" and Quiet NaN is your "regular" NaN. So I have my doubts that Python would be passing a Signaling NaN through COM. How could I find out if a Python float('nan')
is passed through COM as a Signaling NaN or Quiet NaN, or maybe Indeterminate?
Is there any way to make a Signaling NaN versus QuietNaN or Indeterminate in Python, when interfacing with other languages? (Using ctypes
perhaps?) I assume this would be a platform-specific solution, and I'd accept that in this case.
Update: In the TestStand sequence editor, I tried making two variables, one set to NAN
and the other set to IND
. Then I saved it to a file. Then I opened the file and read each variable using Python. In both cases, Python reads them as a nan
float.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
我为您挖掘了一些内容,我认为您也许可以结合 Kevin 的摘要图表。它们解释了用于各种 IEEE 754 浮点数的确切位模式。
如果我阅读有关此 IND 确定值的主题,您可能需要注意的唯一一件事是,当直接在 C 代码中赋值时,该值往往会触发某种浮点中断,导致它变成一个普通的 NaN。这反过来意味着那些人被建议在 ASM 而不是 C 中做这种事情,因为 C 抽象了这些东西。因为这不是我的领域,而且我不确定这种值会在多大程度上混乱Python,我想我应该提到它,这样你至少可以留意任何这种奇怪的行为。 (请参阅此问题的已接受答案)。
参考 Kevin 的摘要图表,显示 < code>float('nan') 实际上从技术上讲是不确定值,而
scipy.nan
是 Quiet NaN。让我们尝试创建一个 Signaling NaN,然后验证它。
不,Signaling NaN 会转换为 Quiet NaN。
现在我们尝试直接制作一个Quiet NaN,然后验证一下。
这就是如何使用 struct.unpack() 生成正确的 Quiet NaN——至少在 Windows 平台上是这样。
I dug a bit for you, and I think you might be able to use the
struct
module in combination with the information on at Kevin's Summary Charts. They explain the exact bit patterns used for the various kinds of IEEE 754 floating point numbers.The only thing you probably will have to be careful for, if I read the topics on this
IND
-eterminate value, is that that value tends to trigger some kind of floating point interrupt when assigned directly in C code, causing it to be turned into a plain NaN. Which in turn meant those people were advised to do this kind of thing in ASM rather than C since C abstracted that stuff away.. Since it is not my field, and that I am not sure to what extent this kind of value would mess with Python, I figured I'd mention it so you can at least keep an eye for any such weird behaviour. (See the accepted answer for this question).Referring to Kevin's Summary Charts, that shows that
float('nan')
is actually technically the Indeterminate value, whilescipy.nan
is a Quiet NaN.Let's try making a Signaling NaN, and then verify it.
No, the Signaling NaN gets converted to a Quiet NaN.
Now let's try making a Quiet NaN directly, and then verify it.
So that's how to make a proper Quiet NaN using
struct.unpack()
--at least, on a Windows platform.nan 的 CPython 定义
当 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()
将其转换为 Pythonfloat
(如果还没有)PyFloat_AsDouble()
> 将其转换为纯 Cdouble
值。PyFloatObject
成员ob_fval
中的 Cdouble
。所以看起来好像我已经从 COM 接口追踪了一个
NaN
到包含Py_NAN
的普通 Cdouble
类型,无论结果如何是在Windows平台上。TestStand NAN 值
现在我已经使用 NI TestStand 进行了尝试。首先我尝试了:
但是在 TestStand 中仍然显示为 IND 。然后我创建了一个 TestStand 文件,其中变量设置为 IND 和 NAN,并从 Python 读取值。事实证明,TestStand 的
NAN
的值为FFFF000000000001
。根据 Kevin 的摘要图表,这是一个负安静的NAN。 TestStand 的IND
确实具有不确定的预期值,FFF8000000000000
。成功
所以,毕竟,我已经成功地从Python在TestStand中设置了一个NAN:
CPython definition of nan
When Python reports a
nan
, where does that come from?Py_NAN
in the CPython C source code(Py_HUGE_VAL * 0.)
Py_HUGE_VAL
is probably defined asHUGE_VAL
--it has a note to say it should beHUGE_VAL
except on platforms where that is broken.float('nan')
which is defined fromPy_NAN
in CPython's C source code.Reading Python and pywin32 Source Code
I've had a look at the C source code for
pywin32
, in particularwin32com
, which forms the Python↔COM translation layer. That code:PyNumber_Float()
to convert it to a Pythonfloat
(if it isn't already)PyFloat_AsDouble()
to convert it to a plain Cdouble
value.double
directly contained in thePyFloatObject
memberob_fval
.So it looks as though I've traced a
NaN
from the COM interface back to a plain Cdouble
type containingPy_NAN
, whatever that turns out to be on the Windows platform.TestStand NAN Value
Now I've tried this with NI TestStand. First I tried:
But that still appeared in TestStand as
IND
. So then I created a TestStand file with variables set toIND
andNAN
, and read the values from Python. It turns out that TestStand'sNAN
has a value ofFFFF000000000001
. According to Kevin's Summary Charts that is a negative quiet NAN. TestStand'sIND
does have the expected value for Indeterminate,FFF8000000000000
.Success
So, after all that, I have succeeded in setting a NAN in TestStand, from Python:
约翰·库克(John Cook)就此发表了一篇很好的文章,可能会有所帮助:
更新:这行不通?
John Cook had a nice post on this that might be helpful:
Update: won't this work?
据我所知,认为 NaN 的符号决定它是否安静的想法似乎有些混乱。相反,惯例是尾数的最高有效位决定了这一点。来自维基百科(添加了重点):
由于大多数实现都符合 IEEE 754-2008,因此这是您应该遵循的约定。一般来说,您不能计划 NaN 的符号位保持一致,即使对于同一平台上的不同 NaN 也是如此。根据此约定,
float('nan')
和scipy.nan
似乎都是安静的 NaN,至少在上面讨论的情况下是如此。From what I can gather, it seems there is some confusion as to thinking that the sign of a
NaN
determines whether or not it is quiet. On the contrary, the convention is that the most significant bit of the mantissa determines this. From Wikipedia (emphasis added):Since most implementations are IEEE 754-2008 conformant, this is the convention you should follow. In general, you cannot plan on the sign bit being consistent for NaNs, even for different NaNs on the same platform. Under this convention,
float('nan')
andscipy.nan
both seem to be quiet NaNs, at least in the cases discussed above.