那么,Float8、Float16、Float32、Float64和Float128到底可以包含多少位数字呢?

2022-04-10 00:00:00 python numpy floating-point precision

问题描述

请原谅我问了这么愚蠢的问题,但我在网上找不到任何答案。

Numpy's dtype documentation只显示每个浮点类型的X位指数和Y位尾数,但我无法将X位指数和Y位尾数转换为小数点之前/之后的确切数字。有什么简单的公式/表格可供查阅吗?

提前谢谢您


解决方案

这不像通常预期的那么简单。对于尾数的准确性,通常有两个值:

  1. 给定十进制表示的值,如果将十进制格式转换为选定的二进制格式(使用默认舍入),则可以保证保留多少位小数。

  2. 给定二进制格式的值,如果将值转换为十进制格式,然后再转换回原始二进制格式(同样,使用默认舍入),则需要多少位十进制数才能使原始值保持不变。

在这两种情况下,小数表示都被视为与使用的指数无关,没有前导和尾随零(例如,0.0123e4、1.23e2、1.2300e2、123、123.0、123000.000e-3都是3位数)。

对于32位二进制浮点数,这两个大小分别是6位和9位十进制数字。在C<;Float.h>;中,它们是flt_dig和flt_decimal_dig。(这很奇怪,32位浮点数为大多数数字保留了7位小数位,但也有例外。) 在C++中,分别查看std::Numeric_Limits<;Float>;::Digits10和std::numeric_limits<;float>;::max_digits10,。

对于64位二进制浮点数,它们分别为15和17(分别为DBL_DIG和DBL_DECIMAL_DIG;以及STD::NUMERIC_LIMITS<;Double>;::{digits10,max_digits10})。

它们的一般公式(thx2@MarkDickinson)

  • ${Format}_Dig(Digits10):floor((p-1)*log10(2))
  • ${Format}_DECIMAL_DIG(Max_Digits10):ceil(1+p*log10(2))

其中p是尾数中的位数(包括标准化IEEE754大小写的隐藏位数)。

另外,在C++numeric limits页上有一些数学解释的评论:

标准的32位IEEE 754浮点类型具有24位小数部分(写入23位,其中一个隐含),这可能表明它可以表示7位小数(24*std::log10(2)是7.22),但相对舍入误差是不一致的,一些具有7位小数的浮点值无法转换为32位浮点数:最小的正数示例是8.589973e9,往返后变为8.589974e9。这些舍入误差不能超过表示中的一位,数字10计算为(24-1)*std::log10(2),即6.92。向下舍入得到值6。

在注释中查找16位和128位浮点值(但请参阅下面的实数128位浮点值)。

对于指数,这比较简单,因为每个边界值(最小规格化、最小反规格化、最大值表示)都是精确的,并且可以很容易地获得和打印。

@PaulPanzer建议使用numpy.finfo。它首先给出以下值({Format}_Dig);可能是您要搜索的内容:

>>> numpy.finfo(numpy.float16).precision
3
>>> numpy.finfo(numpy.float32).precision
6
>>> numpy.finfo(numpy.float64).precision
15
>>> numpy.finfo(numpy.float128).precision
18
但是,在大多数系统上(我的系统是x86-84上的Ubuntu 18.04),这个值对于浮点数128是令人困惑的;它实际上是80位x86"扩展"浮点数,具有64位有效数;实数IEEE754浮点数128有112个有效位数,因此实数值应该在33左右,但是NumPy在这个名称下提供了另一种类型。具体请看here:一般来说,Float128在NumPy中是一种错觉。

更新3:您提到的float8--IEEE754集合中没有这样的类型。人们可以想象这种类型用于一些完全特定的目的,但它的范围太窄,不能用于任何普遍用途。

相关文章