C浮子的精度

通常我们说浮点数在小数点后的精度为6位数。 但是如果我们存储大量的10 ^ 30的数量,我们将不会得到小数点后的6位数。 那么浮点数在小数点后的精度为6位是否正确?

“小数点后6位数字”是无效的,你的例子很好地certificate了这一点。

这是float数据类型的精确规范。

float精度为24位。 根据在线资料,有23位表示二进制点之后的分数,另外还有一个“隐含的前导位”。 这总共提供了24个有效位。

因此,十进制数字大约是:

24 * log(2)/ log(10)= 7.22

这听起来像是在询问精确到小数位 ( 小数点后面的数字),而有效数字 (除了前导和尾随零之外的总位数)是描述数字准确性的更好方法。

你的正确之处在于,当数字较大时,小数点后的位数会发生变化 – 但如果我们说的是精确度,那么当数字较大时,有效数字的数量不会改变。 但是,十进制数的答案并不简单:


现在大多数系统都使用IEE浮点格式来表示C中的数字。但是,如果你处于exception状态,那么值得检查。 单精度IEE float由三部分组成:

  • 符号位(此数字是正数还是负数)
  • (通常也是签名的)指数
  • 分数(指数之前的数字)

正如我们所期望的那样,这都是以二进制forms存储的。


有多少重要数字?

如果您使用的是IEE-754数字,“有多少有效数字”可能不是一种考虑它的简单方法,因为精度是用二进制有效数字而不是十进制来衡量的float s对于小数部分只有23位精度,但由于存在隐含的前导位(除非小数部分全为零,表示最终值为1),因此有24个有效位精度。

这意味着有24个有效的二进制数字 ,这不会转换为精确的十进制有效数字。 您可以使用公式24 * log(2)/ log(10)来确定小数精度有7.225位数,这对您的问题不是一个很好的答案,因为有24个有效二进制数字的数字只有有6位有效小数位数。

因此,单精度浮点数具有6-9个精确的十进制数字 ,具体取决于数字。

有趣的是,您还可以使用此精度计算出可以在单个精度浮点数中成功表示的最大连续整数(从零开始计数)。 它是2 ^ 24,或16,777,216。 您可以精确地存储更大的整数,但前提是它们可以用24个有效二进制数字表示。


进一步的琐事:分数组件的有限大小与导致Javascript的原因相同:

 > console.log(9999999999999999); 10000000000000000 

Javascript数字始终表示为双精度浮点数,具有53位精度。 这意味着在2 ^ 53和2 ^ 54之间,只能表示偶数,因为任何奇数的最后一位都会丢失。

浮点数的精度应以二进制数字而非十进制数字来衡量。 这是因为计算机以二进制数运算,而二进制分数只能接近小数。

语言律师会说,C标准没有指定float的确切宽度,因此依赖于实现,但在任何平台上,您可能会遇到C float意味着IEEE754 单精度数。

IEEE754规定浮点数采用科学计数法 :( – 1) s ×2 e × m
其中s是一位宽, e是八位宽, m是二十三位宽。 在数学上, m是24位宽,因为它总是假设顶部位是1。

因此,可以用该表示近似的最大小数位数是: log 10 (2 24 )= 7.22 。 这近似于七位有效十进制数字,指数范围为2 -126到2 127

请注意,指数是单独测量的。 这就像你使用普通的科学记谱法 ,如“一个人体重72.3公斤= 7.23×10 4克”。 请注意,此处有三位有效数字 ,表示该数字仅精确到100克以内。 但是也有一个完全不同数字的指数 。 你可以拥有一个非常大的指数,只有很少的有效数字,比如“太阳重1.99×10 33克”。 大数字,几位数。

简而言之,浮点数可以存储大约7-8个有效十进制数字 。 让我用一个例子来说明这一点:

 1234567001.00 ^ +---------------- this information is lost .01234567001 ^ +-------------- this information is lost 

基本上,float存储两个值: 1234567和小数点的位置。

现在,这是一个简化的例子。 Floats存储二进制值而不是十进制值。 32位IEEE 754浮点空间有23个“有效位”(加上第一个总是假定为1),大约相当于7-8个十进制数字。

  1234567001.00 (dec) = 1001001100101011111111101011001.00 (bin) gets rounded to 1001001100101011111111110000000.00 = | 23 bits | 1234567040.00 (dec) 

这正是C产生的:

 void main() { float a = 1234567001; printf("%f", a); // outputs 1234567040 }