为何二进制浮点数会出现FLT_DIG与FLT_DECIMAL_DIG取值不等的情况
二进制浮点数两类
*_DIG常量不等的原因 首先明确两类常量的定义:
- 不带
DECIMAL后缀的FLT_DIG/DBL_DIG/LDBL_DIG/FLT16_DIG:指的是可保证十进制数和对应浮点数互转无精度损失的最大十进制有效位数。只要你的原始十进制数有效位数不超过这个值,转成对应浮点数再转回十进制,结果和原数完全一致。 - 带
DECIMAL后缀的FLT_DECIMAL_DIG/DBL_DECIMAL_DIG/LDBL_DECIMAL_DIG/FLT16_DECIMAL_DIG:指的是将浮点数无损转成十进制字符串所需的最小十进制有效位数。你至少要保留这么多位十进制数字,才能把这个字符串转回浮点数时,和原始的浮点数完全相等。
二进制实现的浮点数出现两者不等的核心原因是:二进制和十进制的数位权重是不同底数的幂次,有效位数的转换不存在整数对应关系。我们拿最常见的单精度float举例:它的二进制尾数有23位(不含隐式前导1),对应的精度范围落在6~7位十进制有效数之间:
- 要保证任意6位有效数的十进制数转float再转回十进制完全正确是可以实现的,所以
FLT_DIG取值为6; - 但要把任意float转成十进制再转回去完全不变,6位远远不够,需要至少9位十进制有效数,所以
FLT_DECIMAL_DIG取值为9。
若浮点数类型采用十进制表示,则LDBL_DIG与LDBL_DECIMAL_DIG的取值一致。
这个结论也很好理解:如果浮点数本身就是用十进制存储的,不需要跨进制做舍入转换,互转的精度要求自然是统一的,两类常量的取值就会完全相等。
这个逻辑对所有二进制实现的浮点数都通用,不管是单精度、双精度、长双精度还是半精度,只要底层采用二进制存储,两类*_DIG常量的取值就会存在差异。
内容的提问来源于stack exchange,提问作者pmor
相关产品推荐
相关产品推荐

