开发
浮点数是以科学计数法来保存数据的方式
科学计数法
形如 7.823E5,表示 7.823 * 10^5 = 782500
如何存储?
百度搜索 “浮点数存储”
float
总占用 32 位
根据科学计数法,需要至少存储两部分 7.823 以及 指数 5
在计算机系统中,则增加一位符号位,即正负
- sign: 符号位, 即图中蓝色的方块
- biased exponent: 偏移后的指数位, 即图中绿色的方块
- fraction: 尾数位, 即图中红色的方块
float 精度问题
如上所示,尾数位的存储是23bits,所以实际表达的只有23bits,最大值为16777216(如果保留两位小数,那么就只有16万)
也就是有效数字只能是这么大,再大它就表达不了,例如16777216+1 = 16777217,这个 16777217 它表达不了,测试代码如下:
int tmp = 16777216;
temp += 1;
float f = Convert.ToSingle(tmp);
// f : 16777216.0
也就是它只能表达一个近似值,再来个例子,
int tmp = 16777216;
tmp *= 10;
tmp -= 1;
float f = Convert.ToSingle(tmp);
// f : 167772160.0
如上所示,期望是 167772160-1 = 167772159 ,实际为167772160
float 转换失真问题
例如 10.84 , 到了c# 会变成 10.840000000000003
这是由于浮点数是算出来的,在计算的时候存在失真的情况,
这涉及到转换的知识点:
- 整数转二进制:采用"除2取余,逆序排列"法
- 小数转二进制:采用"乘2取整,顺序排列"法
以0.7为例,直接使用”乘2取整,顺序排列“后可以看到,结果为0.10接上1100的无限循环。
剩余小数 | 乘2 | 取整数位 |
---|---|---|
0.7 | 1.4 | 1 |
0.4 | 0.8 | 0 |
0.8 | 1.6 | 1 |
0.6 | 1.2 | 1 |
0.2 | 0.4 | 0 |
0.4 | 0.8 | 0 |
0.8 | 1.6 | 1 |
0.6 | 1.2 | 1 |
0.2 | 0.4 | 0 |
0.4 | 0.8 | 0 |