一、为何叫浮点数?
相对于浮点数,就是固点数,小数点固定在最右边,也就是整数。浮点数的小数点,根据指数的取值,左右移动。
二、考虑二进制整数,假设只有2个bit,能够表示00,01,10,11,共四个整数,表示范围是[0,3],能够表示这个范围内的全部整数。
三、考虑二进制小数,假设只有2个bit,能够表示多少个小数? 答案也是四个。假设小数点在最左边,分别为00,01,10,11,表示的值分别为0.0,0.25,0.50,0.75。表示范围[0.0,0.75],特别注意:不一样于整数,整数能够表示范围内的每个整数,如[0,3]。而小数只能表示[0.0, 0.75]范围内的四个小数,咱们知道从0.0到0.75有无数个小数,两位二进制只能表示其中的4个。
四、十进制0.0到0.9,有几个可使用二进制表示?
只有两个,0.0和0.5。考虑十进制,小数第一位是1/10,小数第二位是1/100,小数第三位是1/1000,那么二进制呢?
小数第一位是1/2,小数第二位是1/4,小数第三位是1/8,那么0.1 可使用下面的方式表示吗?
a1*1/2 + a2*1/4 + a3*1/8 + ....
存在这样的a1,a2,a3吗?
答案是不存在。
五、0.1+0.2 为何不等于0.3?而是0.30000000000000004
在计算的时候,计算机要把0.1和0.2转化为二进制表示,由上面分析,咱们知道计算机没法准确表示0.1和0.2,只能是无限接近地表示,那么无限接近0.1和0.2的两个值相加,固然不能保证是0.3,可是能够保证的是,结果无限接近0.3。
六、那么怎么解释 0.2+03 会等于0.5呢?
举个例子,计算 1.6+1.8,如今假设不能准确表示1.6和1.8,只能准确表示整数,先转化为最接近的整数,也就是2+2=4,这与1.6+1.8=3.4,再转化为最接近的3,相差为1。那么是否是,全部的计算结果都不许确呢?
不是这样,考虑1.2+1.8 =3,转化为处理是 1+2 =3,计算的结果是准确的。
也就是说,转化过程当中精度缺失,若是两个加数都多了一点,其和多了一点加一点。若是一个加数多了一点,一个加数少了一点,恰好相互抵消,其和恰好很是准确,一点不差。
七、二进制与十进制的转化,
二进制整数转为十进制整数,二进制小数转为十进制小数都简单。
十进制整数转为二进制小数,除2取余,倒序排列。
十进制小数转为二进制小数,乘2取整,顺序排列。用这种方法,能够知道0.1永远不能获得0
八、思考一下,十进制小数0.1不能用二进制准确表示,那么是否是全部的二进制小数,均可以使用十进制准确表示呢?
能够。二进制小数,转为十进制,就是a1/2+a2/4+a3/8....,a1,a2,a3取值为0或者1,那问题就转化为,1除2的n次方,是否是都能除尽。类推一下,0.5,0.25,0.125,每次末位都是5,除2结尾是25,永远都能除尽。
九、从数学的角度分析,对于小数,2进制只能表示1/2, 3进制只能表示1/3, 2/3, 3进制无法表示1/2, 也就是一半,你会说1.5/3 就是一半呀,这就是一个递归的问题,那1.5怎么用3进制表示?无法表示。那么10进制,只能表示1/10, ...9/10, 而恰巧5/10就是1/2, 所以10进制可以表示2进制的任何小数。 spa
十、若是我想让0.1+0.2 等于0.3,怎么办?
从上面分析知道,二进制能够表示可表示范围内的任意一个整数。咱们把0.1和0.2根据小数点分红两部分,同时记住小数点的位置。,分别变成整数相加,再合并进位,在字符串中添加小数点的位置便可。须要注意的是:小数点左边右对齐,小数点右边左对齐。好比:12.46+5.5400,分别为12+5,4600+5400。
代码以下:
string NzbUtils::GetRightDouble(string a, string b)
{
vector<string> aVec;
StringSplit(a,".",aVec,true);
vector<string> bVec;
StringSplit(b,".",bVec,true);
int c1 = atoi(aVec[0].c_str()) + atoi(bVec[0].c_str());
int maxLen = aVec[1].size() > bVec[1].size() ? aVec[1].size():bVec[1].size();
if(maxLen > aVec[1].size())
{
while(maxLen > aVec[1].size())
{
aVec[1]+="0";
}
}
if(maxLen > bVec[1].size())
{
while(maxLen > bVec[1].size())
{
bVec[1]+="0";
}
}
int c2 = atoi(aVec[1].c_str()) + atoi(bVec[1].c_str());
char ch[64] = {0};
sprintf(ch,"%d",c2);
if(strlen(ch) > aVec[1].size())
{
c2 = atoi(ch+1);
c1 = c1+1;
}
char ret[64] = {0};
sprintf(ret,"%d.%d",c1,c2);
return ret;
}