zoukankan      html  css  js  c++  java
  • 浅谈C语言整型与浮点型转换

    本篇博客将阐述、讨论的内容:

    int

          int的范围根据计算机的不同存在16位或32位的差异,以16位举例,最大值为1111 1111 1111 1111,也就是65535,如果出现65536,就会溢出。

         ●unsigned int(无符号整型)

          以16位系统为例,unsigned int能存储的数据范围是0~65535(需要注意整数是以补码形式存放)。其进行的是模数计算,也就是所谓的二进制相加减,计算方法和十进制加减并无区别,但是unsigned int有着正溢出和负溢出的问题。

          对于正溢出与负溢出,诸多基础概念便不再赘述,不懂的朋友可以去回顾计算机组成原理的相关知识。

    这里仅举出一个负溢出的例子:

    进行自然丢弃后,可知结果为0。很明显,产生了负溢出。

         ●接下来,我们说说unsigned int和int的相互转化,代码如下:

    float sum_elements(float a[],unsigend length){
        float result = 0;
        for(int i = 0; i <= length - 1; i++){
            result += a[i];
            return result;
        }
    }
    

          很显然,计算一个数组所有元素之和。但当数组为空时,length输入0,会返回一个存储器错误。为什么呢?请看unsigned int的计算,length是unsigned int 类型,进行的是模数运算,只代表正数,如果出先了0000000(这里有32个0)-00000..01(31个0,1个1)=111…11111(32个1)=UMAX。一个本该为-1的数变成了无符号数最大值,当i取任何不为0的数都发生了非法访问,自然出现了存储器错误,并且任何数都小于UMAX,出现判别式永远为真,进入死循环。解决办法有两种,做一个判断,当传入length<1,直接返回0 or 在之前就将length转化为int。

    浮点数

         ●定点数以及定点数的缺点

          用10进制表示小数早已司空见惯,那么就会想要对二进制做同样的操作,为它也加上小数点。

    但是如此的二进制小数,会出现一些问题不可避免

    ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​
    整数部分小数部分二进制(Representation)
    53/4$101.11_2 $
    27/8$10.111_2$
    17/16$1.0111_2$

    很明显可以发现,只能准确的表示 (x/2^k) 的小数,而不为 (x/2^k) 只能近似。

    ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​ ​
    十进制小数部分二进制(Representation)
    1/3$0.01010101[01]… _2$
    1/5$0.001100110011[0011]… _2$
    1/10$0.0001100110011[0011]… _2$
    而为什么会出现如上结果,就要知到1/3 和 1/5是如何计算的。

    由此可见,当小数无法描述(x/2^k)时,二进制小数便只能取近似值(多采用close to even(靠近偶数))。

    这就暴露定点数的一个重要缺点 ---- 定点数无法标准化。也就是说,关于小数点的位置无法给出一个标准的定点数计算方式,不同小数点的位置给计算定点数增加了难度。与此同时,定点数表示的范围有限,32位的定点数,假设没有整数位,那么所能表示的小数的最小值为:2-32,而32位浮点数仅指数位便可以表示到2-126,由此不难看出,定点数虽然精度高,但标准化和范围大小都比较差。

    所以此时便引出了浮点数来统一二进制小数的表示:

    注:s:表示符号位,只用一个bit表示

    M:表示尾数(significand)(frac)也表示小数位,即能准确表示小数位

    E:表示指数位。

    常用的float,double组成:

    可以看出float有8位指数位,23位尾数位。指数最大可表示的范围为-127~126

    浮点数所表示的一个范围:

    可以得到,浮点数随着大小的不同被分为不同种类,接近0的称为Denormalized,较大的数字被分为Infinity。(关于Denormalized、Infinity等名词请自行了解,这里不再做过多的赘述)。

    Denormalized到NaN的变化:

    浮点数相加的公式:

    浮点数的加法和乘法由于近似的原因,经常无法实现加法的结合律和乘法分配律,如下所示:

    (3.14+le10)-1e10=0.0,因为3.14+1e10会舍入,3.14会丢失(1e10表示1*101010)

    然而3.14+(1e10-1e10)=3.14

    le20*(le20-le20)=0.0

    le20le20-le20le20=NaN,由于溢出的关系,可见在数字大的情况下不满足加法结合律和乘法分配律。

    最后,关于int,float,double之间相互转换可能的问题:

    当在int,float以及double格式之间进行强制转换时,程序改变数值和位模式的原则如下(假设int为32位):

    ●从int转换成float,数字不会溢出,但可能被舍入。

    ●从int或float转换成double,因为double有更大的范围(也就是可表示值得范围),也有更高得精度(即有效位数),所以能保留精确得数值。

    ●从double转换成float,因为范围要小一些,所以值可嫩溢出为+∞或-∞。且由于精度较小,它还可能被舍入。

    ●从float或double转换成int,值将会向0舍入。例如1.999将转换为1。进一步说,值可能会溢出。C语言标准没有对这种情况指定固定的结果。而与Inter兼容的微处理器指定位模式[10…00](字长为ω时的TMinω)为整数不确定值。一个从浮点数到整数的转换,如果不能为该浮点数找到一个合理的整数近似值,就会产生一个这样的值。因此,表达式(int)+le10会得到-21483648,即从一个正值变成了一个负值。

    参考博主:写代码的柯长(CSDN)、Jamesjiang2050(博客园)

  • 相关阅读:
    linux打包解压包(.tar .gz .tar.gz .zip)
    centos安装fusesshfs通过挂载目录实现数据双向同步
    WSL远程访问Windows下的MySQL方法
    Linux中hugepage的使用方法
    Python科普系列——类与方法(下篇)
    Treevalue(0x02)——函数树化详细解析(上篇)
    Treevalue(0x03)——函数树化详细解析(下篇)
    Python科普系列——类与方法(上篇)
    个人网站迁移之旅:从博客到知识库,从 Hexo 到 Docusaurus
    wpf 动画结束后保留end值,动画结束后会失去绑定,可以在completed事件重新进行绑定
  • 原文地址:https://www.cnblogs.com/RpgMaker/p/13896060.html
Copyright © 2011-2022 走看看