您可以选中convert the float to a hex representation;符号、指数和分数各有一个单独的部分。如果分数只使用前6个十六进制数字(其余7个数字必须为零),和第6位是偶数(因此最后一位是而不是集),则64位双浮点数是否适合32位单精度。指数限制在-126和127之间:
import math
import re
def is_single_precision(
f,
_isfinite=math.isfinite,
_singlepat=re.compile(
r'-?0x[01]\.[0-9a-f]{5}[02468ace]0{7}p'
r'(?:\+(?:1[01]\d|12[0-7]|[1-9]\d|\d)|'
r'-(?:1[01]\d|12[0-6]|[1-9]\d|\d))$').match):
return not _isfinite(f) or _singlepat(f.hex()) is not None or f == 0.0
您可以选中convert the float to a hex representation;符号、指数和分数各有一个单独的部分。如果分数只使用前6个十六进制数字(其余7个数字必须为零),和第6位是偶数(因此最后一位是而不是集),则64位双浮点数是否适合32位单精度。指数限制在-126和127之间:
^{pr2}$float.hex()
方法非常快,比通过struct或numpy的往返更快;您可以在半秒内创建一百万个十六进制表示:regex引擎也相当快,通过上面函数中优化的名称查找,我们可以在大约1.1秒内测试100万个浮点值:
上面的工作是因为浮点的二进制32格式为小数分配了23位。指数分配8位(有符号)。正则表达式只允许设置前23位,指数在有符号8位数字的范围内。在
另请参见
但这可能不是你想要的!以1/3或1/10为例。这两个值都需要浮点值中的近似值,并且都未通过测试:
您可能需要采用启发式方法;如果十六进制值在分数的前6位数中都是零,或者指数在(-126,127)范围之外,则转换为double会导致过多的损失。在
为了完整起见,下面是注释中提到的“round tripping through struct”方法,它的优点是不需要numpy,但仍能给出准确的结果:
与
is_single_precision_numpy()
的时间比较:所以在我的机器上似乎也更快了。在
如果您想要一个简单的解决方案来覆盖几乎所有的角点情况,并且能够正确地检测出超出范围的指数以及较小精度的信息丢失,您可以使用NumPy将您的潜在浮点转换为
np.float32
对象,然后与原始值进行比较:这将自动处理可能存在问题的情况,例如
^{pr2}$float32
次正常范围内的值。例如:使用基于
hex
的解决方案很难轻松处理这些情况。在虽然没有@Martijn Pieters基于regex的解决方案快,但速度仍然可观(大约是基于regex的解决方案的一半)。以下是时间安排(其中
is_single_precision_re_hex
正是Martijn的答案)。在不幸的是,虽然几乎所有的角点情况(次正常值、无穷大值、有符号的零、溢出等)都得到了正确的处理,但是有一种情况下,这个解决方案不适用于:
floatval
是NaN。在这种情况下,is_single_precision_numpy
将返回False
。这可能对你的需求有影响也可能不重要。如果这很重要,那么添加一个额外的isnan
检查就可以做到了:相关问题 更多 >
编程相关推荐