版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/github_33873969/article/details/78040129

从学了C语言之后,一直习惯于C/C++任意的强制转化,但是C语言的强制转化却总是带来意想不到的后果,在这里,我将从int,float,double的本质上讲解这些可能出现的问题以及解决办法,在下面你将看到:

OK,现在好戏开始。

  • int

    • unsigned int: unsigned int所进行的是模数计算,就是正常的二进制相加减,计算方法和十进制加减并无区别,但是unsigned int有着正溢出和负溢出的问题,如下图计算所示:

      这一点是我们需要注意的地方。
    • int:int所使用的是32位补码,关于补码的运算,在这里就不赘述了,大部分计算机导论的书籍都有相关说明。
    • 接下来,要说的就是unsigned int和int的相互转化,请看如下代码:
/* WARNING: This is buggy code */
float sum_elements(float a[],unsigned length)
{int i;float result=0;for(i=0;i<=length-1;i++){result+=a[i];return result;}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12

这段代码计算一个数组所有元素之和,看起来似乎没什么问题。但是当你的数组为空的时候,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.或者,在之前就将length转化为int。

  • 浮点数(float,double的理解)

    • 什么是定点数,定点数有什么缺点:
      我们用二进制数表示整数,我们也想用二进制表示小数。自然而然,我们会像十进制的小数一样,在二进制上加上小数点,例如1.001111122,

      但是这样的二进制会出现什么样的问题呢?请看下面的二进制小数
整数部分 小数部分 二进制(Representation)
5 3/4 101.1122

大家观察一下,二进制小数有什么特点。
只能准确的表示x/2kx/2k只能近似,请看下面的小数

十进制小数 二进制(Representation)
1/3 0.01010101[01]…22

[0011]表示无限循环小数
为什么会出现这样的计算结果,请看下面1/3 和 1/5是如何计算的。

2−2+2−4+2−6.....+2−2n=∑n=1∞2−2n=limn→+∞14(1−2−2n)1−(2−2)=132−2+2−4+2−6.....+2−2n=∑n=1∞2−2n=limn→+∞14(1−2−2n)1−(2−2)=13

1/5就复杂了点

2−3+2−4+2−7+2−8+2−11+2−12+.......+21−4n+2−4n=∑n=1∞21−4n+∑n=1∞2−4n=limn→+∞18(1−21−4n)1−(2−4)+limn→+∞116(1−2−4n)1−(2−4)=215+115=152−3+2−4+2−7+2−8+2−11+2−12+.......+21−4n+2−4n=∑n=1∞21−4n+∑n=1∞2−4n=limn→+∞18(1−21−4n)1−(2−4)+limn→+∞116(1−2−4n)1−(2−4)=215+115=15

可见,当小数不能表示为

x2k x2k 

s:表示符号位,只用一个bit表示
M:表示尾数(significand)(frac)也表示小数位,即能准确表示小数位
E:表示指数位,简单来说就是位数的多大。
那么,我们来看一下,我们最常用的float,double是怎么组成的:

明显的看出,float有8位指数位,23位尾数位。指数最大可表示的范围为-127~126,但浮点数的指数计算有一点技巧要用到:E-Bias。
下面是浮点数所表示的一个范围:

大家可以清楚的看到浮点数随着大小的不同被分成好几种,接近0的被称为Denormalized,比较大的数字被分为Infinity,接下来介绍这几种数字的特征:
Normalized:这是最常见的一种情况,指数位EXP不为0(不小),EXP不全为1(不大)。此时,阶码(这个2EE-1,k表示指数位的位数,float单精度即32位浮点为127,double双精度为1023。故float单精度的E范围为-126~127,对于双精度为-1022~+1023。
而对于尾数位,即小数位:相当于得到的数为1.M(M表示尾数位)
下面就到了重点了,这也是浮点数经常被大家忽略的地方。
Denormalized:当阶数E全为0的时候,被称为Denormalized,那么它的指数位就变成了E=1-Bias, 之所以不用-Bias,而用1-Bias,是为了实现与Normalized的数实现完美过渡,具体如何过渡的图片会在下面给出。
而Denormalized的尾数有什么特点呢:如果frac为0,说明该数为0,但是不知道是+0还是-0。因为,前面的符号位未知。如果frac不为0的话,那么实际的数字表示为0.M(M为尾数位),记住,此时前面是0.,因为只有是0.最终才能接近0
Infinity:当指数位全为1,frac尾数位为0的时候表示Infinity(可以表示无穷大),分别取符号位为1或者0,表示正无穷或负无穷。可以满足Infinity相乘或除,表示溢出。
NaN:not a number,即指数位全为1,frac尾数位不全为0.
一张图可以表示Normailized,Denormalized,Infinity,NaN

这张图说明,从Denormalized到NaN有什么变化:

可以看到在Denormalize使用E=1-Bias,并且M前取0,实现了从Largest denorm到Smallest norm完美过渡。
- 浮点数的rounding
上文提到无论是定点数还是浮点数都只能表示有限的位数,那么舍入就显的是一个很重要的环节了。浮点数采取的舍入方法,小于一半的向下舍入,大于一半的向上舍入,在中间的,close to even(向偶数舍入),下面是几个二进制例子:
Format A:
There are k=3 exponent bits. The exponent bias is 3.
There are n=4 fraction bits.
Format B:
There are k=4 exponent bits. The exponent bias is 7.
There are n=3 fraction bits.
要求给出A,将A转化为B
前一半为A,后一半为B

0110000 1 0111000 1
1011110 712712

可以看出第二,三,四的问题的关键在于进位
三的A为:0.11001,即到B先转化为1.1001,明显B的frac只有三位,所有根据close to even,需要接近偶数,所以,round down:1.100,符合。
比较有问题的是最后一个:000 0001 。首先,000说明是Denormalize,则该数表示为0.0001*2−2−2,由于B是4位exp,所以不会是最小的数,所以由Denormalize->Normalize,答案也为1/64
为什么要选择,close to even呢?如果全部的数字都为0.01要精确到小数点后一位的话,如果是四舍五入,那么最后的误差将是0.01*n,但如果是close to even的,认为偶数和奇数是等概率出现,就很小的避免误差往一边倒的情况。

  • 浮点数的计算
    首先先来两个公式
    x+ff)
    但是3.14+(1e10-1e10)=3.14
    le20*(le20-le20)=0.0
    le20*le20-le20*le20=NaN,由于溢出的关系,可见在数字大的情况下不满足加法结合律和乘法分配律

最后,来看看double,float和int相互转化可能的问题

判断以下式子是否正确:

A.正确,因为double的frac为32位和int相同,不会丢失信息。
B.错误,因为float的frac为23位小于int,会丢失信息。
C.错误。double比float精度高。从double转float会丢失信息。
D.正确。
E.正确。符号数正负转化只取决于符号位。
F.正确。浮点数在进行运算的时候会全部转化为浮点数。
G.正确。

H.错误。如果f+d溢出,结果为0.

C语言的int, float,double相互转化 (从本质上理解可能的问题)相关推荐

  1. c语言算式中有double和int,C语言当中int,float,double,char这四个有什么区别?

    区别在以下方面: 一.定义方面: 1.int为整数型,用于定义整数类型的数据 . 2.float为单精度浮点型,能准确到小数点后六位 . 3.double为双精度浮点型,能准确到小数点都十二位 . 4 ...

  2. C语言当中int,float,double,char这四个有什么区别?

    区别在以下方面: 一.定义方面: 1.int为整数型,用于定义整数类型的数据 . 2.float为单精度浮点型,能准确到小数点后六位 . 3.double为双精度浮点型,能准确到小数点都十二位 . 4 ...

  3. C 语言实例 - 计算 int, float, double 和 char 字节大小

    C 语言实例 - 计算 int, float, double 和 char 字节大小C 语言实例 C 语言实例使用 sizeof 操作符计算int, float, double 和 char四种变量字 ...

  4. 演示多组int,float,double的数与 2,2.0f,2.0d的除法运算和取模运算,如有兴趣,可自行分析对比结果

    因为各种基本数据类型所占用的存储空间各不相同,所以在进行各种计算时,有可能存在精度题.计算机的操作要在内存中进行,而内存容量有限:另一方面,持久化存储设备的存储空间也有限,内存中的数据可能需要持久化保 ...

  5. C++ int float double类型的数据大小端转化

    以下代码抄自<网络多人游戏架构与编程>,可以支持float.int.double等数据类型数据的大小端转换,测试代码为: void TestByteSwap() {int32_t test ...

  6. C/C++语言中计算int,float,double,char四种数据类型所能表示的数据范围

    char        1字节    short       2字节    int         4字节    long        4字节    long long   8字节    float ...

  7. [C]C语言基本语句(5/7)→ 用scanf语句输入int, float, double, char型数据

    当需要用键盘输入一个或几个数字或字符,就要用到scanf 例1: 基本格式 #include<stdio.h> int main() {int a,b;scanf("%d,%d& ...

  8. int, float, double之间不得不说的故事

    抱歉我用了一个这么"二"的题目,不过二点就二点吧,希望内容还不算太二. 其实学习过编程的同学,都对这三个东西再熟悉不过了.int,又称作整型,在.net中特指的是Int32,为32 ...

  9. 【编程】char unsigned int float double long 字节数

    定义方面: 1.int为整数型,用于定义整数类型的数据 . 2.float为单精度浮点型,能准确到小数点后六位 . 3.double为双精度浮点型,能准确到小数点都十二位 . 4.char为字符型,用 ...

最新文章

  1. bind98-内网智能DNS之master服务器构建
  2. 1、user权限表详解
  3. 获取windows帐户的SID值
  4. 编译原理之词法分析、语法分析、语义分析,【精炼总结】
  5. 【BIM入门实战】Revit 图元分类有哪三种?Revit图元分类图文详解
  6. 一天一个C++程序(六)
  7. leetcode 80. 删除有序数组中的重复项 II
  8. 敏捷外包工程系列之四:合理选择质量管理的等级(一)
  9. CCF NOI1079 合法C标识符
  10. 星期天写了点蛋疼的东西(3)
  11. 冀教版四年级上册计算机教案,冀教版信息技术四年级上册教案
  12. android 博饼代码,中秋博饼游戏下载
  13. SQL注入入侵动网站(MSSQL)
  14. 身份证号提取年龄方法python_身的解释|身的意思|汉典“身”字的基本解释
  15. Linux部署FAQ
  16. 冰点服务器内的客户端显示脱机,冰点还原精灵DeepFreeze企业版控制台中不显示客户端...
  17. php+head+下载,CMSHead 开源的PHPCMS系统下载/CMSHead 开源的PHPCMS系统官方下载-太平洋下载中心...
  18. linux命令查看cpu序列号,Linux下用命令查看CPU ID以及厂家等信息
  19. Nginx负载均衡请求转发
  20. 58同城离线计算平台设计与实践(大数据进阶)

热门文章

  1. MSIL实用指南-比较运算
  2. springmvc框架自带的异常处理器SimpleMappingExceptionResolver的使用
  3. 20155307 实验四 Android程序设计
  4. PowerDesigner 反向工程生成ER图
  5. PHP代码审计基础手册
  6. [python] LDA处理文档主题分布及分词、词频、tfidf计算
  7. 【数据结构与算法】之深入解析“分割回文串II”的求解思路与算法示例
  8. LeetCode Algorithm 543. 二叉树的直径
  9. 将森林转换为对应的二叉树,若在二叉树中,结点u时结点v的父结点的父结点,则在原来的森林中,u和v可能具有的关系是( )
  10. 632. Smallest Range Covering Elements from K Lists 最小区间