c 浮点数精度丢失 '浮动'与'双'精度




浮点数精度丢失 (5)

C中的浮点数使用IEEE 754编码。

这种类型的编码使用符号,有效数字和指数。

由于这种编码,许多数字将会有小的变化以允许它们被存储。

而且,有效数字的数量可以稍微变化,因为它是二进制表示,而不是小数。

单精度(浮点)给你23位有效位,8位指数和1位符号位。

双精度(双精度)为您提供52位有效位,11位指数和1位符号位。

代码

float x  = 3.141592653589793238;
double z = 3.141592653589793238;
printf("x=%f\n", x);
printf("z=%f\n", z);
printf("x=%20.18f\n", x);
printf("z=%20.18f\n", z);

会给你输出

x=3.141593
z=3.141593
x=3.141592741012573242
z=3.141592653589793116

输出741012573242的第三行是垃圾,第四行116是垃圾。 双打总是有16位有效数字,而花车总是有7位有效数字? 为什么双打没有14位有效数字?


双打总是有16位有效数字,而花车总是有7位有效数字?

不。双数总是有53个有效 ,浮点数总是有24个有效 (除非规范,无穷和NaN值,但这些是另一个问题的主题)。 这些是二进制格式,你只能用二进制数字(比特)清楚地说明它们表示的精确度。

这与多少数字可以存储在二进制整数中的问题类似:无符号的32位整数可以存储具有多达32位的整数,其不精确地映射到任何小数位数:所有整数至多可以存储9位十进制数字,但也可以存储大量10位数字。

为什么双打没有14位有效数字?

double的编码使用64位(1位为符号,11位为指数,52位显式有效位和一位隐式位),这是用于表示浮点数(32位)的位数的两倍


float:23位有效位,8位指数和1位符号位。

双:52位有效位,11位指数和1位符号位。


由于IEEE 754的工作原理并不完全是精度的,而且二进制不能很好地转化为十进制。 如果您有兴趣,请查看该标准。


它通常基于基数为2的指数和有效数的有效数字,而不是以10为底数。从我在C99标准中可以看出的情况来看,浮点数和双精度并没有指定的精度(除了1和1 + 1E-5 / 1 + 1E-7区分[ floatdouble ])。 然而,有效数字的数量留给实施者(以及他们在内部使用哪个基地,换句话说,一个实施可以决定根据基数为3的18位数的精度)。 [1]

如果您需要了解这些值,则在float.h中定义常量DBL_MANT_DIGFLT_MANT_DIG (和DBL_MANT_DIG / LDBL_MANT_DIG )。

它被称为double的原因是因为用来存储它的字节数是浮点数的两倍(但这包括指数和有效数)。 IEEE 754标准(由大多数编译器使用)为有效位分配比位数更多的位( float为23到9, float为52到12),这就是为什么精度增加了一倍多的原因。

1:第5.2.4.2.2节( http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1256.pdf







floating-point