是否有公式可以找到浮点数中指数或有效位数的位数?
Posted
技术标签:
【中文标题】是否有公式可以找到浮点数中指数或有效位数的位数?【英文标题】:Is there a formula to find the numbers of bits for either exponent or significant in a floating point number? 【发布时间】:2020-06-29 04:29:43 【问题描述】:最近,我对在浮点数上使用位移位来进行一些快速计算很感兴趣。
为了让它们以更通用的方式工作,我想让我的函数使用不同的浮点类型,可能通过模板,不仅限于float
和double
,还包括“半角”或“四倍宽度”浮点数等等。
然后我注意到:
- Half --- 5 exponent bits --- 10 signicant bits
- Float --- 8 exponent bits --- 23 signicant bits
- Double --- 11 exponent bits --- 52 signicant bits
到目前为止,我认为exponent bits = logbase2(total byte) * 3 + 2
,
这意味着 128 位浮点数应该有 14 个指数位,而 256 位浮点数应该有 17 个指数位。
但是,后来我了解到:
- Quad --- 15 exponent bits --- 112 signicant bits
- Octuple--- 19 exponent bits --- 237 signicant bits
那么,有没有一个公式可以找到它?或者,有没有办法通过一些内置函数来调用它? 首选 C 或 C++,但对其他语言开放。
谢谢。
【问题讨论】:
注意:没有保证,至少没有来自 C++ 标准。实现用于浮点编码的内容由实现者决定,但可能会在 IEEE 浮点标准中定义。 IEEE 754,很常见。 wiki page for IEEE 754 什么会阻止您将计数直接硬编码到您的程序中,因为它们都是标准化的? 任何人都可以定义自己的浮点格式并分配他们认为合适的位。关于 IEEE-754 格式,有几个很好的指针here 关于历史和选择。 @Ranoiaetep 考虑到即使是 256 位浮点数的稀有性,我想说一旦您想要/需要添加支持,除了实际实现DBL_MANT_DIG
以基数 2 double
的有效位数提供 bits
的数量。可在预处理器时使用。
【参考方案1】:
通过内置函数提供的特性
C++ 通过std::numeric_limits
模板提供此信息:
#include <iostream>
#include <limits>
#include <cmath>
template<typename T> void ShowCharacteristics()
int radix = std::numeric_limits<T>::radix;
std::cout << "The floating-point radix is " << radix << ".\n";
std::cout << "There are " << std::numeric_limits<T>::digits
<< " base-" << radix << " digits in the significand.\n";
int min = std::numeric_limits<T>::min_exponent;
int max = std::numeric_limits<T>::max_exponent;
std::cout << "Exponents range from " << min << " to " << max << ".\n";
std::cout << "So there must be " << std::ceil(std::log2(max-min+1))
<< " bits in the exponent field.\n";
int main()
ShowCharacteristics<double>();
样本输出:
浮点基数为 2。 有效数字中有 53 个以 2 为底的数字。 指数范围从 -1021 到 1024。 所以指数字段中必须有 11 位。C 还通过在<float.h>
中定义的DBL_MANT_DIG
等宏定义提供信息,但标准仅定义类型float
(前缀FLT
)、double
(DBL
)的名称,和 long double
(LDBL
),因此支持其他浮点类型的 C 实现中的名称将无法预测。
请注意,C 和 C++ 标准中指定的指数与 IEEE-754 中描述的常用指数不同:它被调整为缩放为 [½, 1) 而不是 [1, 2) 的有效数字,所以它比通常的 IEEE-754 指数大一。 (上面的示例显示了从 -1021 到 1024 的指数范围,但 IEEE-754 的指数范围是 -1022 到 1023。)
公式
IEEE-754 确实提供了推荐字段宽度的公式,但它并不要求 IEEE-754 实现符合这些,当然 C 和 C++ 标准也不需要 C 和 C++ 实现符合 IEEE-754。交换格式参数在IEEE 754-2008 3.6中规定,二进制参数为:
对于 16、32、64 或 128 位的浮点格式,有效位宽度(包括前导位)应为 11、24、53 或 113 位,指数字段宽度应为 5、8 、11 或 15 位。 否则,对于k位的浮点格式,k应该是32的倍数,有效位宽度应该是k−round(4•log2k)+13,指数字段应该是round(4•log2k )-13.【讨论】:
+1 用于跟踪参考。在最后一点可能值得注意的是,该公式仅适用于k >= 128
(它实际上也匹配k = 64
的11
位,但它被1
和2
用于@ 987654336@).【参考方案2】:
答案是否定的。
使用多少位(甚至使用哪种表示)由编译器实现者和委员会决定。并且无法猜测委员会的决定(不,这不是任何合理定义“最佳”的“最佳”解决方案......这正是那天在那个房间发生的事情:历史事故)。
如果你真的想达到那个水平,你需要在你想要部署的平台上实际测试你的代码,并添加一些#ifdef
宏观(或询问用户)以找到你的代码的系统类型正在运行。
另外请注意,根据我的经验,编译器在类型别名方面非常激进(甚至令人讨厌)的一个领域是浮点数。
【讨论】:
最后一段怎么强调都不为过:如果不调用 UB 或通过至少一个memcpy()
调用,则无法操作浮点位,如果您确实需要结果,则需要两个。即使union
也不足以定义类型双关语。【参考方案3】:
我想看看是否有一个公式是说如果将 512 位浮点数作为标准输入,它会自动使用它,而无需更改任何内容
我不知道有一个已发布的标准可以保证未来格式(*)的位分配。过去的历史表明,最终选择有几个考虑因素,例如,请参阅Why do higher-precision floating point formats have so many exponent bits? 处的答案和链接。(*) 编辑:请参阅末尾添加的注释 em>。
对于猜谜游戏,IEEE-754 定义的现有 5 种二进制格式暗示指数位数的增长略快于线性。例如,适合这 5 个数据点的一个(随机)公式可能是(WA 表示法)exponent_bits = round( (log2(total_bits) - 1)^(3/2) )
。
这可以预见假设的 binary512 格式将为指数分配 23 位,尽管 IEEE 当然不受这种事后猜测的任何约束。
以上只是一个恰好匹配5个已知指数的插值公式,当然不是唯一这样的公式。例如,在 oeis 上搜索序列 5,8,11,15,19
会找到 18 个列出的整数序列,其中包含该序列作为子序列。
[ EDIT ] 正如@EricPostpischil 的answer 中指出的那样,IEEE 754-2008 实际上列出了total_bits >= 128
的公式exponent_bits = round( 4 * log2(total_bits) - 13 )
(公式实际上适用于total_bits = 64
,也一样,虽然它不适用于= 32
或= 16
)。
上面的经验公式与128 <= total_bits <= 1472
的参考IEEE 匹配,特别是IEEE 还为binary512 提供23
指数位和binary1024 的27
指数位>.
【讨论】:
这个公式必须是渐近线性的,不管它是如何开始的...... @MadPhysicist 2 b 位值的乘积必须至少线性才能适合 (b+1) 位值,这是一个基本原理在linked 答案中引用。除此之外,我没有看到严格线性的硬性要求,除非施加额外的约束。 如果你想在无穷大时留下任何小数部分,它最多只能是线性的。 @MadPhysicist 我的意思是log2(b)
中的线性。例如,对于指数位和尾数位,上述经验公式的增长速度都快于对数线性增长。【参考方案4】:
与上面提到的概念类似,这里有一个替代公式(只是重新排列了一些项),它将计算指数的无符号整数范围([32,256,2048,32768,524288]
,对应于 [ 5,8,11,15,19
]-powers-of-2) 无需调用 round 函数:
uint_range = ( 64 ** ( 1 + (k=log2(bits)-4)/2) )
*
( 2 ** -( (3-k)**(2<k) ) )
(a) x ** y
表示 x-to-y-power
(b) 2 < k
是一个布尔条件,应该只返回 0 或 1。
函数至少从 16 位到 256 位应该是准确的。除此之外,这个公式产生的指数大小为
– 512-bit : 23
– 1024-bit : 27
– 2048-bit : 31
– 4096-bit : 35
(超过 256 可能不准确。即使是 27 位宽的指数也允许 +/- 6700 万的指数,一旦计算出 2 次方,则可以使用超过 4000 万个十进制数字。)
从那里到 IEEE 754 指数只是log2(uint_range)
的问题
【讨论】:
以上是关于是否有公式可以找到浮点数中指数或有效位数的位数?的主要内容,如果未能解决你的问题,请参考以下文章