二进制浮点数中DECIMAL_DIG减DIG的差值为何是2或3?
核心原因解释
首先明确两个宏的定义和计算规则:
xxx_DIG:表示该二进制浮点数类型可保证无损互转的十进制数最大有效位数。任意不超过该位数的十进制数,转成对应浮点数再转回十进制,结果和原值完全一致。计算公式为floor((p-1) * log10(2)),其中p是浮点数尾数的总比特数(含隐式前导1)。xxx_DECIMAL_DIG:表示把该二进制浮点数转成十进制字符串时,需要的最小有效位数,可保证十进制字符串转回浮点数后和原值完全一致。计算公式为ceil(1 + p * log10(2))。
差值只有2或3的推导
log10(2)是无理数,数值约为0.3010,因此p * log10(2)永远不会是整数,我们设p * log10(2) = k + f,其中k是整数,0 < f < 1:
- 计算
xxx_DECIMAL_DIG:ceil(1 + k + f) = k + 2(因为f>0,1+k+f的整数部分是k+1,向上取整结果就是k+2) - 计算
xxx_DIG:floor((p-1)*log10(2)) = floor(p*log10(2) - log10(2)) = floor(k + f - 0.3010)
这里只会出现两种情况:
- 当
f > 0.3010时:k + f - 0.3010大于k、小于k+1,向下取整结果为k,差值为(k+2) - k = 2 - 当
f < 0.3010时:k + f - 0.3010大于k-1、小于k,向下取整结果为k-1,差值为(k+2) - (k-1) =3
示例对应验证
你给出的常见浮点数场景完全匹配推导结果:
- float(p=24):
24*log10(2)≈7.224,f=0.224<0.3010,差值为3,对应FLT_DECIMAL_DIG - FLT_DIG == 9 - 6 == 3 - double(p=53):
53*log10(2)≈15.953,f=0.953>0.3010,差值为2,对应DBL_DECIMAL_DIG - DBL_DIG == 17 - 15 == 2 - x86 80位long double(p=64):
64*log10(2)≈19.264,f=0.264<0.3010,差值为3,对应LDBL_DECIMAL_DIG - LDBL_DIG == 21 - 18 == 3 - float16(p=11):
11*log10(2)≈3.311,f=0.311>0.3010,差值为2,对应FLT16_DECIMAL_DIG - FLT16_DIG == 5 - 3 == 2
额外疑问解答
所有标准二进制实现的浮点数,该差值确实只能是2或者3,没有其他可能。因为推导过程中唯一的变量是f,f的取值范围只有小于或大于0.3010两种情况,不存在第三种可能,也不会出现其他差值。
内容的提问来源于stack exchange,提问作者pmor
相关产品推荐
相关产品推荐

