Python是否提供了获取浮点值的功能,该函数是通过将现有浮点值的最低有效位递增而得到的?
我正在寻找类似于std::nextafter
C
++ 11中添加的功能的东西。
这里有五个(实际上是四个半)解决方案。
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
如果您没有Python
3.9或更高版本,但是可以访问NumPy,则可以使用numpy.nextafter
。对于常规Pythonfloat
,其语义与匹配math.nextafter
(尽管说Python的语义与NumPy的语义匹配会更公平,因为NumPy在Python之前
很早就 可以使用此功能)。
>>> from numpy import nextafter, inf
>>> nextafter(100.0, inf)
100.00000000000001
nextafter
自己包装CC在中指定nextafter
功能math.h
(例如,参见C99的7.12.11.3节);这正是Python> =
3.9包装并在其math
模块中公开的函数。如果您没有Python
3.9或更高版本,则可以使用ctypes
或cffi
动态调用C
nextafter
,也可以编写一个简单的Cython包装器或公开C的Python
C扩展nextafter
。
struct
模块进行位操作如果您愿意(在实践中几乎总是安全的)假设Python正在使用IEEE
754浮点,那么编写提供的Python函数非常容易nextafter
。需要一些注意才能使所有极端情况正确。
IEEE 754二进制浮点格式经过精心设计,因此从一个浮点数到“下一个”数的转换就像递增位表示一样简单。它适用于范围内的任何数字[0, infinity)
,可以跨越指数边界和次法线。要生成nextUp
覆盖整个浮点范围的版本,您还需要处理负数,无穷大,nan和涉及负零的一种特殊情况。以下是nextUp
Python中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]
的实施nextDown
和nextAfter
再这个样子。(请注意,这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)
如果x
是肯定的但不太float
愿意,并且您愿意假设IEEE 754
binary64格式和语义,则有一个非常简单的解决方案:下一个从x
is向上浮动x / (1 - 2**-53)
,下一个从x
is向下浮动x * (1 - 2**-53)
。
更详细地,假设满足以下所有条件:
然后,该数量1 - 2**-53
可以精确地表示为a float
,并且给定非正态Python浮点正x
,x / (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]
,因此足以保证最接近的浮点数z
是nextafter(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。 问题答案: 你需要和