任何有小数点的数值,都会被编译器解释为浮点数,也叫实数。
1.浮点数的储存
为了存储浮点数,计算机将分配 4 字节(32 位)内存。
- 1 位用于符号
- 8 位用于指数部分
- 23 位为底数部分(小数部分)
我们一步一步说明计算机如何存储浮点数。
- 将浮点数转换为二进制数,我们把 10.75 转化成浮点数 (1010.11) 2;
- 使转换后的二进制数转化成标准形式
- 把浮点数统一以下列形式 1.小数位 bit * 2^指数1010.11 转换成标准形式:1.01011 * 2 3
-
- 在指数位增加一个偏移值 (偏置值)
在浮点数中存储中,不利用 2 的补码来存储负数。 但为了克服没有减法器问题,引入了偏移的概念,这样可以把浮点数的负数转变成正值并参与运算。这样,无论浮点数是负值还是正值,它们都会将偏移值添加到指数值以降低实现复杂性。
计算偏移值的公式是 : biasn = 2n-1 – 1;
8比特位的偏移值就是:2 7 – 1 = 127
因此,归一化指数值将是,实际指数 + 偏差值为 130 (3 + 127) – 130 的二进制形式是 10000010
10.75 的二进制储存如下图所示:
符号位为0代表该数是正数。
指数部分是130(二进制 10000010)
底数数值是 1.01011,这里我们可以消除点 (.) 之前 1和(.) ,因为无论数字是多少,我们总是要归一化为 1.something。 因此,无需存储 1和(.)。只需在 (.) 后面 01011 取位即可。
浮点数的类型声明使用float关键字,可以用来声明浮点数变量。
2.浮点变量 (实型变量)
任何有小数点的数值,都会被编译器解释为浮点数。所谓“浮点数”就是使用 m * be 的形式,存储一个数值,m
是小数部分,b
是基数(通常是2
),e
是指数部分。这种形式是精度和数值范围的一种结合,可以表示非常大或者非常小的数。
单精度(float型)、双精度(double型)和长双精度(long double型)三类。
单精度型占4个字节(32位)内存空间,其数值范围为3.4E-38~3.4E+38,只能提供七位有效数字。双精度型占8 个字节(64位)内存空间,其数值范围为1.7E-308~1.7E+308,可提供16位有效数字。
实型变量定义的格式和书写规则与整型相同。例如:
float c = 10.5;
double a,b,c; // a,b,c为双精度实型量
上面示例中,变量c的就是浮点数类型。
float类型占用4个字节(32位),其中8位存放指数的值和符号,剩下24位存放小数的值和符号。float类型至少能够提供(十进制的)6位有效数字,指数部分的范围为(十进制的)-37到37,即数值范围为10-37到1037。
有时候,32位浮点数提供的精度或者数值范围还不够,C 语言又提供了另外两种更大的浮点数类型。
- double:占用8个字节(64位),至少提供13位有效数字。
- long double:通常占用16个字节。
注意,由于存在精度限制,浮点数只是一个近似值,它的计算是不精确的,比如 C 语言里面0.1 + 0.2并不等于0.3,而是有一个很小的误差。
if (0.1 + 0.2 == 0.3) // false
C 语言允许使用科学计数法表示浮点数,使用字母e
来分隔小数部分和指数部分。
double x = 123.456e+3; // 123.456 x 10^3
// 等同于
double x = 123.456e3;
上面示例中,e后面如果是加号+,加号可以省略。注意,科学计数法里面e的前后,不能存在空格。
另外,科学计数法的小数部分如果是0.x或x.0的形式,那么0可以省略。
0.3E6
// 等同于
.3E6
3.0E6
// 等同于
3.E6
例1.浮点数精度显示
#include <stdio.h>
int main()
{
int a = 1;
char b = 'G';
double c = 3.14;
printf("Hello World!\n");
// printing the variables defined
// above along with their sizes
printf("Hello! I am a character. My value is %c and "
"my size is %lu byte.\n",
b, sizeof(char));
// can use sizeof(b) above as well
printf("Hello! I am an integer. My value is %d and "
"my size is %lu bytes.\n",
a, sizeof(int));
// can use sizeof(a) above as well
printf("Hello! I am a double floating point variable."
" My value is %lf and my size is %lu bytes.\n",
c, sizeof(double));
// can use sizeof(c) above as well
printf("Bye! See you soon. :)\n");
return 0;
}
结果
Hello World!
Hello! I am a character. My value is G and my size is 1 byte.
Hello! I am an integer. My value is 1 and my size is 4 bytes.
Hello! I am a double floating point variable. My value is 3.140000 and my size is 8 bytes.
Bye! See you soon. :)
Process returned 0 (0x0) execution time : 0.871 s
Press any key to continue.
例2. 浮点数的精度显示
#include
int main(void)
{
float a;
double b;
a=33333.33333;
b=33333.33333333333333;
printf("a=%f\nb=%f\n",a,b);
return 0;
}
a=33333.332031
b=33333.333333
Process returned 0 (0x0) execution time : 0.851 s
Press any key to continue.