书中说c标准为六位有效数字提供浮点精度,但这不是真的吗?

Aki*_*mbo 3 c floating-point

我正在阅读Stephen Prata撰写的C Primer Plus,其中介绍浮点数的第一种方法之一是谈论它们在某一点上的准确性.它特别说"C标准规定浮子必须能够代表至少六个有效数字......浮子必须准确表示前六个数字,例如,33.333333"

这对我来说很奇怪,因为它听起来像一个浮点数精确到六位数,但事实并非如此.1.4存储为1.39999 ......依此类推.你还有错误.

究竟提供了什么?数字的准确度是否有截止值?

在C中,如果没有编译器警告,你不能在浮点数中存储超过六个有效数字,但为什么呢?如果你要做六个以上的数字,它似乎就像准确一样.

关于下溢和次正规数的部分使这更令人困惑.当你有一个浮点数最小的数字,除以10,你得到的错误似乎不是正常的?它们似乎只是上面提到的常规舍入误差.

那么为什么这本书说浮点数精确到六位数以及如何与常规舍入误差不同?

Eri*_*hil 6

假设您有一个带有q位有效数字的十进制数字:

d q -1.d q -2 d q -3 ... d 0,

让我们也把它变成一个浮点小数,这意味着我们用10的幂来缩放它:

d q -1.d q -2 d q -3 ... d 0 •10 e.

接下来,我们将此数字转换为float.许多此类数字无法准确表示float,因此我们将结果舍入到最接近的可表示值.(如果存在平局,我们舍入以使低位数均匀.)结果(如果我们没有溢出或下溢)是一些浮点数x.通过浮点数的定义(在C 2018 5.2.4.2.2 3中),它由某个基数中的一些数字表示,该基数由该基数按比例缩放到幂.假设它是基数为2,x是:

b p -1.b p -2 b p -3 ... b 0 •2 p.

接下来,我们将此float x转换为带有q位有效数字的十进制数.类似地,floatx可能无法准确表示为带有q位的十进制数字,因此我们得到一些可能的新数字:

n q -1.n q -2 n q -3 ... n 0 •10 m.

事实证明,对于任何float格式,都有一些数字q,如果我们开始的十进制数字限于q个数字,那么这个往返转换的结果将等于原始数字.q个数字的每个十进制数字,当舍入到float然后返回到q个十进制数字时,将产生起始编号.

在2018 C标准中,第5.2.4.2.2节第12段告诉我们这个数字q必须至少为6(C实现可能支持更大的值),并且C实现应该为它定义一个预处理器符号(in float.h)叫FLT_DIG.

因此,考虑到您的示例编号1.4,当我们将其转换float为IEEE-754基本32位二进制格式时,我们得到的确是1.39999997615814208984375(这是它的数学值,为方便起见以十进制显示;对象中的实际位代表它在二进制).当我们以全精度将其转换为十进制时,我们得到"1.39999997615814208984375".但是如果我们将它转​​换为带有四位数的十进制数,我们得到"1.40000".所以1.4在往返中幸存下来.

换句话说,这是不正确的,一般有六个十进制数字可以表示在float没有变化,但是这是事实,float携带足够的信息,你可以恢复从它六个小数位数.

当然,一旦你开始算术,错误通常会复合,你不能再依赖六位小数.