浅谈C语言整型与浮点型转换

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

浅谈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/4101.112
27/810.1112
17/16 1.01112
很明显可以发现,只能准确的表⽰x/2k的⼩数,⽽不为x/2k只能近似。

⼗进制⼩数部分⼆进制(Representation)
1/30.01010101[01] (2)
1/50.001100110011[0011] (2)
1/100.0001100110011[0011] (2)
⽽为什么会出现如上结果,就要知到1/3 和 1/5是如何计算的。

由此可见,当⼩数⽆法描述x/2k时,⼆进制⼩数便只能取近似值(多采⽤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(博客园)
Processing math: 100%。

相关文档
最新文档