浮点数及缺陷
数字分为整数和小数.
char int
……都是用来存储整数的.
那么小数如何保存呢?
小数在我们的C语言中,用float和double来表示.
float对应着4个字节
double对应着8个字节.
long
double 16个字节
计算机不管是任何数据,最后都会转换成1和0来存储.
而制定float和double是按照IEEE编码规范的.
跟原码补码反码和Ascll、Unicode码,还有x86.X64一样.
都是为了一个原则,统一规范.大家都按照这个套路来.
深究为什么这样设计没有太大意义.
浮点数在内存里面和整数存储理解是不一样的。
浮点数需要考虑小数点。
就拿float来举例吧。
127.53这是一个小数。
还记得科学计数法吗?用科学计算法可以将小数点的位置固定。
我们可以这样表示:12.753 x 101也可以写成1.2753 x 102结果都等同于127.53。
8.25这个小数也可以表示成8.25
x 10 0
-0.012这个小数也可以表示为1.2 x 10 -2
十进制整数转换二进制整数大家用计算器很容易转换。
假如我们现在要把20.5这个小数放到float里面.
那如何把20.5转换成2进制数呢?
分两次转换。
整数除以2,商继续除以2,得到0为止,将余数逆序排列。
小数乘以2,取整,小数部分继续乘以2,取整,得到小数部分0为止,将整数顺序排列。
20.5
20 / 2= 10 余数为0
10/
2= 5 余数为0
5 / 2= 2 余数为1
2 / 2 =1 余数为0
1/ 2= 0
余数为1
整数的部分是10100
所有的整数一定可以转换成一个二进制数.
第1位符号位。正数为0,负数为1.
第2位到第9位指数位。
是0000
0100这样存储吗?
不是的,float需要指数+111 1111(127)然后把结果存储进去。
100+111 1111=10000011
(131)
0-1000 0011-0100 1000 0000 0000 0000 000 =
这就是20.5的float二进制内存表示。
30.3
20=10100
0.3*2=0.6(0)
0.6*2=1.2(1)
0.2*2=0.4
(0)
0.4*2=0.8 (0)
0.8*2=1.6 (1) //进入循环
0.6*2=1.2(1)
0.2*2=0.4
(0)
0.4*2=0.8 (0)
0.8*2=1.6
(1)
二进制为10100.010011001(无限循环)
科学计算法:1.01000 1001 1001 1001
E100
0-1000 0011-01000 1001 1001 1001 1001 10= 这就是20.3的float二进制内存表示。
float
1 8 23
double
1 11 52
32位单精度
单精度二进制小数,使用32位存储。
1 8 23 位长
偏正值 +127 0111
1111
64位双精度
双精度二进制小数,使用64位存储。
1 11 52
位长
偏正值 +1023 011 1111 1111
所以,不难发现,有些10进制小数,用二进制小数来表示的时候,是无法准确的表示,只是相似。
这就造成了,小数计算会造成结果不精准。
而我们知道货币是精确到2位的。1.53
一元五角三分。
所以货币用这种计算是很危险的。
float v1;
float v2;
float v3;
#include <stdio.h>
#include <stdlib.h>
void main() {
v1 = 20.3;
v2 = 13.8;
v3 = v1 + v2;
printf("v3 is %f\n",v3);
system("pause");
}
dvd vcd 这是视频格式编码
mp3 wav
同样的音质
mp3= 5M
wma=2M
wma wmv //微软公司
jpg png gif bmp
//解码器