python float 精度损失_在转换为Protobuf / C float时,Python float何时会失去精度?

您可以检查将float转换为十六进制表示形式;符号,指数和分数各自得到一个单独的部分.如果分数仅使用前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

float.hex()方法非常快,比通过struct或numpy往返更快;您可以在不到半秒的时间内创建100万个十六进制表示:

>>> timeit.Timer('(1.2345678901e+26).hex()').autorange()

(1000000, 0.47934128501219675)

正则表达式引擎也相当快,并且在上面的函数中优化了名称查找,我们可以在大约1.1秒内测试100万个浮点值:

>>> import random, sys

>>> testvalues = [0.0, float('inf'), float('-inf'), float('nan')] + [random.uniform(sys.float_info.min, sys.float_info.max) for _ in range(2 * 10 ** 6)]

>>> timeit.Timer('is_single_precision(f())', 'from __main__ import is_single_precision, testvalues; f = iter(testvalues).__next__').autorange()

(1000000, 1.1044921400025487)

上面的工作原理是因为float的binary32格式为分数分配了23位.指数被分配8位(有符号).正则表达式只允许设置前23位,并且指数在有符号的8位数字的范围内.

另见

这可能不是你想要的!以1/3或1/10为例.两者都是需要在浮点值中近似的值,并且两者都未通过测试:

>>> (1/3).hex()

'0x1.5555555555555p-2'

>>> (1/10).hex()

'0x1.999999999999ap-4'

您可能不得不采用启发式方法;如果您的十六进制值在分数的前6位数中全部为零,或者在(-126,127)范围之外的指数,则转换为double将导致太多损失.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值