如何在Python中将数字转换为12位精度?

4

我需要在Python中存储一个12位精度的浮点变量。

我知道将变量转换为浮点数有float函数,但是如何指定浮点数的比特大小呢?例如(12,16,...)


2
这是一种相当不寻常的浮点格式。它的规格是什么?你确定它不是80位,或者可能是80位填充到128位吗?请参阅https://en.wikipedia.org/wiki/Extended_precision#x86_extended_precision_format - PM 2Ring
1
我认为这是一个合理的问题,尽管表面上看起来有些奇怪,与关闭/踩票相反。一开始我也想投票关闭,但在意识到OP的背景是数学/物理强大之后,我仔细检查了更多。作为未来问题的建议,也许可以像您上面那样放一些相关的介绍或强调自己的研究努力,以便读者意识到它更加复杂。 - Alexander McFarlane
好的,但正如我所说,这是一种不寻常的格式。更令人惊讶的是,嵌入式系统会使用如此高精度的浮点数。在Python中处理它不会很容易,但您需要有其精确规格。 - PM 2Ring
1
即使您只想创建随机数据并且不需要对这些数字进行任何实际算术运算,您仍然需要数据规范,以便不会创建无效的位模式。 - PM 2Ring
@StarBucK:你确定这不是12位格式而不是12字节格式吗?我很难想象哪种嵌入式卡片需要那种精度。 - Mark Dickinson
显示剩余5条评论
3个回答

7

如其他答案中所述,在纯Python数据类型中并不存在这个功能,请参阅文档

但是,您可以使用numpy来指定显式数据类型,例如:

  • numpy.float16
  • numpy.float32
  • numpy.float64
你还可以使用numpy.float96扩展精度,因为12个字节等于96位,这似乎是你想要的。
import numpy as np
high_prec_array = np.array([1,2,3], dtype=np.float96)

注意事项

正如评论和链接所指出的那样,这并不是真正的12字节精度。相反,它是80位(10字节),再加上2个零字节。如果您只关心兼容性,这可能已经足够了。

此精度可能在所有平台上都不可用

在下表中,platform? 表示该类型可能不适用于所有平台。与不同C或Python类型的兼容性是指:如果两种类型的数据大小相同且以相同的方式解释,则它们是兼容的。

还要阅读有关使用此类奇特类型的注意事项

我发现这很有启发性。如果您想绝对保证96位精度,那么Python不是正确的选择,因为可用扩展精度中的固有模糊性来自于C分布中的模糊性。考虑到您的物理背景,我建议使用Fortran以确保稳定性。
在C++中定义自己的类型
对于感兴趣的高级用户,可能可以定义自己的数据类型。numpy指南user defined types states中提到:

作为添加数据类型能力的有用应用示例,是将任意精度浮点数的数据类型添加到NumPy。

如果你非常希望在python中保留代码,那么你可以尝试使用boost/multiprecision/cpp_bin_float.hpp

NumPy不支持12字节的浮点类型。在某些平台上,它有一种称为“float96”的类型,但那是Intel x87使用的80位(10字节)IEEE 754-1985 64位精度扩展格式(1个符号位,15个指数位,64个有效位,没有隐藏位),并用两个零字节填充到12字节。我知道这些信息在您的链接中是隐含的,但我认为这个答案如果按原样呈现会误导人。 - Mark Dickinson
是的,我仍在研究它 - 这就是为什么信息有些矛盾的原因。这似乎是一个相当复杂的问题!我认为 OP 只需要将格式设置为 12 字节以实现兼容性,因此即使最后两个字节由两个零字节填充,也不应该有影响。 - Alexander McFarlane
评论(尤其是StarBucK的最后一个评论)似乎表明他确实需要12位二进制位。他之前提到了字节,只是因为他不知道比特和字节之间的区别。我认为在任何语言中都没有太多实现12位浮点数。 - Rudy Velthuis

2

“float类型...是固定的。通常为64位,但可能会改变”这句话不太清楚。它是固定的还是取决于实现? - chux - Reinstate Monica
1
这取决于实现。在特定的实现中,它不会改变。但一个实现可能是64位,另一个实现可能是32位。 - Pac0
至少对于CPython而言,它是有效固定的,因为Python的float使用C的double,并且假设sizeof(double)== 8被纳入了CPython源代码中。 (这很糟糕,但实际上似乎到目前为止没有引起任何真正的问题。)而IronPython和Jython则运行在(.NET和Java)平台上,这些平台明确说明Double是IEEE 754二进制64。MicroPython可能会做一些有趣的事情,但我不知道。 - Mark Dickinson

1

gmpy2 的开发版本支持 96 位 IEEE 数字类型。

>>> import gmpy2
>>> gmpy2.version()
'2.1.0a1'
>>> gmpy2.set_context(gmpy2.ieee(96))
>>> gmpy2.get_context()
context(precision=83, real_prec=Default, imag_prec=Default,
        round=RoundToNearest, real_round=Default, imag_round=Default,
        emax=4096, emin=-4175,
        subnormalize=True,
        trap_underflow=False, underflow=False,
        trap_overflow=False, overflow=False,
        trap_inexact=False, inexact=False,
        trap_invalid=False, invalid=False,
        trap_erange=False, erange=False,
        trap_divzero=False, divzero=False,
        allow_complex=False,
        rational_division=False)
>>> gmpy2.mpfr(1)/7
mpfr('0.14285714285714285714285714',83)
>>> 

在旧版本的gmpy2中也是可能的,但需要更多的努力。

>>> import gmpy2
>>> gmpy2.version()
'2.0.8'
>>> ieee96 = gmpy2.context(precision=83, emax=4096, emin=-4175, subnormalize=True)
>>> gmpy2.set_context(ieee96)
>>> gmpy2.mpfr(1)/7
mpfr('0.14285714285714285714285714',83)
>>> 

您可能需要向下滚动以直接从 https://github.com/aleaxit/gmpy 下载源代码。一些早期的 wheel 文件可在 https://pypi.python.org/pypi/gmpy2/2.1.0a1 上获得。

免责声明:我维护 gmpy2


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接