zoukankan      html  css  js  c++  java
  • 浮点数精度

    1、为什么叫浮点数?
       相对于浮点数,就是固点数,小数点固定在最右边,也就是整数。浮点数的小数点,根据指数的取值,左右移动。
    2、考虑二进制整数,假设只有2个bit,可以表示00,01,10,11,共四个整数,表示范围是[0,3],可以表示这个范围内的所有整数。
    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个。
    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吗?
       答案是不存在。
    5、0.1+0.2 为什么不等于0.3?而是0.30000000000000004
       在计算的时候,计算机要把0.1和0.2转化为二进制表示,由上面分析,我们知道计算机无法准确表示0.1和0.2,只能是无限接近地表示,那么无限接近0.1和0.2的两个值相加,当然不能保证是0.3,但是可以保证的是,结果无限接近0.3。
    6、那么怎么解释 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,计算的结果是准确的。
    也就是说,转化过程中精度缺失,如果两个加数都多了一点,其和多了一点加一点。如果一个加数多了一点,一个加数少了一点,刚好相互抵消,其和刚好非常准确,一点不差。
    7、二进制与十进制的转化,
       二进制整数转为十进制整数,二进制小数转为十进制小数都简单。
       十进制整数转为二进制小数,除2取余,倒序排列。
       十进制小数转为二进制小数,乘2取整,顺序排列。用这种方法,可以知道0.1永远不能得到0
    8、思考一下,十进制小数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,永远都能除尽。

    9、从数学的角度分析,对于小数,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进制的任何小数。 

    10、如果我想让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;
    }
  • 相关阅读:
    常用公式 距离、波形、力
    代码字体
    关于flash缩放的详细解释
    色调
    工程项目1
    使用double无法得到数学上的精确结果的原因及为何不能用double来初始化BigDecimal
    第一次测验感受
    原码,补码,反码的概念及Java中使用那种存储方式
    static的含义
    第一次测试代码
  • 原文地址:https://www.cnblogs.com/nzbbody/p/4391708.html
Copyright © 2011-2022 走看看