当前位置: 首页 > 面试题库 >

如何获得浮点序列中的下一个值?

周辉
2023-03-14
问题内容

Python是否提供了获取浮点值的功能,该函数是通过将现有浮点值的最低有效位递增而得到的?

我正在寻找类似于std::nextafterC
++ 11中添加的功能的东西。


问题答案:

这里有五个(实际上是四个半)解决方案。

解决方案1:使用Python 3.9或更高版本

2020年10月发布的Python
3.9包括一个新的标准库函数math.nextafter,该函数直接提供此功能:用于math.nextafter(x, math.inf)将下一个浮点数向正无穷大。例如:

>>> from math import nextafter, inf
>>> nextafter(100.0, inf)
100.00000000000001

如果查看方法提供的十六进制表示,则可以更容易地验证此函数是否确实
产生下一个浮点数float.hex

>>> 100.0.hex()
'0x1.9000000000000p+6'
>>> nextafter(100.0, inf).hex()
'0x1.9000000000001p+6'

Python
3.9还引入了一个密切相关且经常有用的伴随函数math.ulp,该函数给出一个值与下一个远离零的值之间的差:

>>> from math import ulp
>>> nextafter(100.0, inf) - 100.0
1.4210854715202004e-14
>>> ulp(100.0)
1.4210854715202004e-14

解决方案2:使用NumPy

如果您没有Python
3.9或更高版本,但是可以访问NumPy,则可以使用numpy.nextafter。对于常规Pythonfloat,其语义与匹配math.nextafter(尽管说Python的语义与NumPy的语义匹配会更公平,因为NumPy在Python之前
很早就 可以使用此功能)。

>>> from numpy import nextafter, inf
>>> nextafter(100.0, inf)
100.00000000000001

解决方案3:nextafter自己包装C

C在中指定nextafter功能math.h(例如,参见C99的7.12.11.3节);这正是Python> =
3.9包装并在其math模块中公开的函数。如果您没有Python
3.9或更高版本,则可以使用ctypescffi动态调用C
nextafter,也可以编写一个简单的Cython包装器或公开C的Python
C扩展nextafter

解决方案4:通过struct模块进行位操作

如果您愿意(在实践中几乎总是安全的)假设Python正在使用IEEE
754浮点,那么编写提供的Python函数非常容易nextafter。需要一些注意才能使所有极端情况正确。

IEEE 754二进制浮点格式经过精心设计,因此从一个浮点数到“下一个”数的转换就像递增位表示一样简单。它适用于范围内的任何数字[0, infinity),可以跨越指数边界和次法线。要生成nextUp覆盖整个浮点范围的版本,您还需要处理负数,无穷大,nan和涉及负零的一种特殊情况。以下是nextUpPython中IEEE
754功能的标准兼容版本。它涵盖了所有极端情况。

import math
import struct

def nextup(x):
    # NaNs and positive infinity map to themselves.
    if math.isnan(x) or (math.isinf(x) and x > 0):
        return x

    # 0.0 and -0.0 both map to the smallest +ve float.
    if x == 0.0:
        x = 0.0

    n = struct.unpack('<q', struct.pack('<d', x))[0]
    if n >= 0:
        n += 1
    else:
        n -= 1
    return struct.unpack('<d', struct.pack('<q', n))[0]

的实施nextDownnextAfter再这个样子。(请注意,这nextAfter不是IEEE
754所指定的函数,因此对于IEEE特殊值应该发生的情况有一些猜测。在这里,我遵循Python的decimal.Decimal类所基于的IBM
Decimal Arithmetic标准。)

def nextdown(x):
    return -nextup(-x)

def nextafter(x, y):
    # If either argument is a NaN, return that argument.
    # This matches the implementation in decimal.Decimal
    if math.isnan(x):
        return x
    if math.isnan(y):
        return y

    if y == x:
        return y
    elif y > x:
        return nextup(x)
    else:
        return nextdown(x)

(部分)解决方案5:浮点运算

如果x是肯定的但不太float愿意,并且您愿意假设IEEE 754
binary64格式和语义,则有一个非常简单的解决方案:下一个从xis向上浮动x / (1 - 2**-53),下一个从xis向下浮动x * (1 - 2**-53)

更详细地,假设满足以下所有条件:

  • 您无需担心IEEE 754极端情况(零,无穷大,次法线,nans)
  • 您不仅可以假定IEEE 754 binary64浮点 格式 ,还可以假定IEEE 754 binary64 语义 :即,所有基本算术运算均已根据当前舍入模式正确舍入。
  • 您可以进一步假设当前的舍入模式为IEEE 754默认的“舍入为偶数”模式。

然后,该数量1 - 2**-53可以精确地表示为a float,并且给定非正态Python浮点正xx / (1 - 2**-53)将会匹配nextafter(x, inf)。类似地,x * (1 - 2**-53)将匹配nextafter(x, -inf),除了在x最小正法向值的拐角情况下2**-1022

使用此方法时要注意一件事:表达式2**-53将从pow系统的数学库中调用您,通常期望pow正确取整并不安全。有许多更安全的方法可以计算此常数,其中一种是使用float.fromhex。这是一个例子:

>>> d = float.fromhex('0x1.fffffffffffffp-1')  # 1 - 2**-53, safely
>>> d
0.9999999999999999
>>> x = 100.0
>>> x / d  # nextup(x), or nextafter(x, inf)
100.00000000000001
>>> x * d  # nextdown(x), or nextafter(x, -inf)
99.99999999999999

这些技巧可在浮点数的正常范围内正常工作,包括在尴尬的情况下,例如精确的2的幂。

对于证据的草图:表明x / d比赛nextafter(x, inf)正正常的x,我们可以通过两个动力,而不会影响正确性规模,因此在证明,我们可以不失一般性该损失承担0.5 <= x < 1.0。如果我们写z精确 的数学值x / d(认为是实数,而不是一个浮点数),则z - x等于x * 2**-53 / (1 - 2**-53)。结合不等式0.5 <= x <= 1 - 2**-53,我们可以得出结论2**-54 < z - x <= 2**-53,由于浮点数在间隔中正好2**-53间隔开[0.5, 1.0],因此足以保证最接近的浮点数znextafter(x, inf)。证明x * d相似。



 类似资料:
  • 我试图得到浮点数的尾数(只是为了学习),但它没有按预期工作。 比如说5.3的尾数是53,对吗?我尝试了以下代码: 它打印了2726298。它不应该去掉指数位并留下53吗?我尝试了很多事情,但总是这样。我做错了什么?

  • 我想从现有的浮点数中提取1个十进制浮点数。 我在Objective-C中做过:使浮点只显示两位小数 知道如何在Swift中实现吗?

  • 本文向大家介绍MySQL从一列值列表中仅获取浮点数,包括了MySQL从一列值列表中仅获取浮点数的使用技巧和注意事项,需要的朋友参考一下 让我们首先创建一个表- 使用插入命令在表中插入一些记录- 使用select语句显示表中的所有记录- 这将产生以下输出- 以下是从列表中获取浮点数的查询- 这将产生以下输出-

  • 我在学习如何使用java 8流时,发现了一些奇怪的事情。 <代码>数组。stream()具有除浮点数组之外的所有方法: <代码>数组。流(int[]):int流 同样,有int、双精度等的Stream实现,但没有浮点数: 有什么原因吗? 使用浮动流的推荐方法是什么?

  • 我有一个程序,我需要将一个变量设置为C中最低的可表示(非无限)双精度浮点数。如何将变量设置为最低的双精度浮点值? 我尝试使用std::numeric_limits。我没有使用C 11,所以我无法尝试使用最低()函数。我尝试使用max(),但是当我尝试它时,它返回无穷大。我还尝试从max()中减去一个值,希望这样我就可以得到一个可表示的数字。 输出: 如何将上面示例中的low_值设置为最低的可表示双

  • 问题内容: 假设我的表包含以下内容: 每次通过while循环。我想获取价格值的总和,但ID中的每个不同值仅获取一次 因此,以上述示例为例,我将得到类似以下内容的信息: 补充一下,我可能偶然发现了类似的帖子。问题是其他职位使用Oracle,另一方面我正在使用MySQL。 问题答案: 你需要和