浮点数及缺陷

数字分为整数和小数.
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
//解码器
posted @ 2017-08-26 00:45  随意就好欧巴  阅读(722)  评论(0编辑  收藏  举报