IEEE浮点数到精确的base10字符串

时间:2015-09-17 21:58:25

标签: c++ c floating-point precision

如果printf('%.9e', value)是IEEE单精度浮点数(C / C ++浮点数),value是否总是打印value的确切base10表示?

如果printf('%.17e', value)是IEEE双精度浮点数(C / C ++ double),那么value是否一样?

如果没有,我该怎么办?

似乎printf('%.17f', value)printf('%.17g', value)不会。

2 个答案:

答案 0 :(得分:3)

  

printf('%。9e',value)是否总是打印出确切的base10表示?

没有。考虑0.5,0.25,0.125,0.0625 ......每个值都是前面的一半,并且每个递减的幂为2需要另一个小数位。

float,通常binary32可以表示关于pow(2,-127)的值和更低的法线。它需要127个小数位才能完全代表那些。即使仅计算重要数字,数字也是89+。一台计算机上的示例FLT_MIN 正好

0.000000000000000000000000000000000000011754943508222875079687365372222456778186655567720875215087517062784172594547271728515625

FLT_TRUE_MIN,最小的非零子法线是151位数:

0.00000000000000000000000000000000000000000000140129846432481707092372958328991613128026194187651577175706828388979108268586060148663818836212158203125

相比之下,FLT_MAX只需39位数。

340282346638528859811704183484516925440

很少需要{em>完全十进制代表float。将它们打印到FLT_DECIMAL_DIG(通常为9)有效数字就足以唯一地显示它们。许多系统不会打印超过几十个有效数字的精确十进制表示。

我使用的绝大多数系统都打印float/double至少DBL_DIG个有效数字(通常为15+)。大多数系统至少以DBL_DECIMAL_DIG(通常为17+)个有效数字为准。

Printf width specifier to maintain precision of floating-point value会遇到这些问题。

printf('%.*e', FLT_DECIMAL_DIG - 1, value)会将float打印到足够的小数位,以便将其扫描回来并获得相同的值 - (往返)。

答案 1 :(得分:2)

this Wikipedia article中解释了32位浮点数的IEEE-754格式。

下表显示了每个位的位权重,假设指数为0,表示为1.0 <= N < 2.0。表中的最后一个数字是小于2.0的最大数字。

从表中可以看出,您需要在小数点后打印至少23位数才能从32位浮点数中获取精确的十进制数。

3f800000 1.0000000000000000000000000   (1)
3fc00000 1.5000000000000000000000000   (1 + 2^-1)
3fa00000 1.2500000000000000000000000   (1 + 2^-2)
3f900000 1.1250000000000000000000000   (1 + 2^-3)
3f880000 1.0625000000000000000000000   (1 + 2^-4)
3f840000 1.0312500000000000000000000   (1 + 2^-5)
3f820000 1.0156250000000000000000000   (1 + 2^-6)
3f810000 1.0078125000000000000000000   (1 + 2^-7)
3f808000 1.0039062500000000000000000   (1 + 2^-8)
3f804000 1.0019531250000000000000000   (1 + 2^-9)
3f802000 1.0009765625000000000000000   (1 + 2^-10)
3f801000 1.0004882812500000000000000   (1 + 2^-11)
3f800800 1.0002441406250000000000000   (1 + 2^-12)
3f800400 1.0001220703125000000000000   (1 + 2^-13)
3f800200 1.0000610351562500000000000   (1 + 2^-14)
3f800100 1.0000305175781250000000000   (1 + 2^-15)
3f800080 1.0000152587890625000000000   (1 + 2^-16)
3f800040 1.0000076293945312500000000   (1 + 2^-17)
3f800020 1.0000038146972656250000000   (1 + 2^-18)
3f800010 1.0000019073486328125000000   (1 + 2^-19)
3f800008 1.0000009536743164062500000   (1 + 2^-20)
3f800004 1.0000004768371582031250000   (1 + 2^-21)
3f800002 1.0000002384185791015625000   (1 + 2^-22)
3f800001 1.0000001192092895507812500   (1 + 2^-23)

3fffffff 1.9999998807907104492187500

有一点需要注意的是,在1和2之间只有2 ^ 23(约8百万)个浮点值。但是,小数点后面有10 ^ 23个数字,23位数,所以十进制很少数字具有精确的浮点表示。

作为一个简单的例子,数字1.1 具有精确的表示。最接近1.1的两个32位浮点值是

3f8ccccc 1.0999999046325683593750000
3f8ccccd 1.1000000238418579101562500