python - 可能有 `` a < b 和 not(a - b < 0 )`` with floats

标签 python floating-point

a < b and not(a - b < 0)

由于 float 舍入错误, float 可能吗? 有例子吗?

最佳答案

[此答案旨在作为对 Patricia Shanahan 已经给出的良好答案的学究补充。该答案涵盖了正常情况;在这里,我们担心的是您在实践中不太可能遇到的边缘情况。]

是的,这是完全可能的。这是我非常普通的基于 Intel 的 Mac 笔记本电脑的 Python session :

Enthought Canopy Python 2.7.6 | 64-bit | (default, Jan 29 2014, 17:09:48) 
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import evil
>>> a = float.fromhex('1p-1022')
>>> b = float.fromhex('1.01p-1022')
>>> a < b and not(a - b < 0)
True

当然,正如导入所示,这里发生了一些邪恶的事情。这是evil.py的内容. (警告:这是高度特定于平台的,并且所写的仅适用于 OS X。如果 Python 已被编译为使用 SSE2 指令而不是 x87 单元进行浮点运算,则此变体应该适用于 Linux/x64 .我对Windows一无所知。)

# Being lazy: we should really import just the things we need.
from ctypes import *

# Type corresponding to fenv_t from fenv.h.  (Platform specific!)
class fenv_t(Structure):
    _fields_ = [("control", c_ushort), ("status", c_ushort),
                ("mxcsr", c_uint), ("reserved", c_char * 8)]

# Wrap fegetenv and fesetenv from the C library.
libc = CDLL("/usr/lib/libc.dylib")
fegetenv = libc.fegetenv
fegetenv.restype, fegetenv.argtypes = c_int, (POINTER(fenv_t),)
fesetenv = libc.fesetenv
fesetenv.restype, fesetenv.argtypes = c_int, (POINTER(fenv_t),)

# Set the flush-to-zero (FTZ) bit in the MXCSR control register.
env = fenv_t()
fegetenv(pointer(env))
env.mxcsr |= 1 << 15
fesetenv(pointer(env))

所以我们在这里做的是弄乱 MXCSR 控制寄存器中保存的 FPU 设置。在支持 SSE 指令集的 Intel 64 处理器上,有两个有趣的标志会影响涉及次正规数的运算行为。设置 FTZ(清零)标志后,会将算术运算的任何次正规输出替换为零。 DAZ(denormals-are-zero)标志在设置时会导致算术运算的任何次正规输入都被视为零。这些标志的意义在于,它们可以显着加快涉及次正规数的运算,但会牺牲对 IEEE 754 标准的遵从性。在上面的代码中,我们在 MXCSR 控制寄存器中设置了 FTZ 标志。

现在我们选择ab这样两个ab是正常的,但它们的差异是次正常的。然后 a < b将是真的(像往常一样),但是 a - b将是 -0.0 , 以及比较 a - b < 0失败。

要点是,您使用的浮点格式 是 IEEE 754 格式是不够的。您还需要知道您的操作符合标准。 FTZ 模式是可能失败的一种方式的示例。将此与 Patricia Shanahan 的回答联系起来:evil.py 中的代码正在关闭 IEEE 754 promise 的逐渐下溢。 (感谢@EricPostpischil 在评论中指出这一点。)

关于python - 可能有 `` a < b 和 not(a - b < 0 )`` with floats,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21590883/

相关文章:

c++ - 非 IEEE 754 浮点类型的大小如何受到限制?

python - 生成新进程时导入会发生什么情况?

python - 如何实现高速、一致的采样?

python - 如何将声音分配给 Pygame 中的 channel ?

c - 随机 float

types - F# Int 的平方根

Python - 除法仅在使用浮点除数时有效

python - Tornado - 使用 render() 时找不到记录器 "tornado.application"的处理程序

python - 从 PDF 中提取文本 - 所有页面和输出 - 使用 Python 的文件

c++ - 错误 "cannot convert ' float '到 'float...' ..."