int与float是我们每天编程都用的两种类型,但是我们真的足够了解它们吗。昨天在博客园看到一个比较老的笑话: “昨天晚上下班回家,一民警迎面巡逻而来。突然对我大喊:站住!民警:int 类型占几个字节?  我:4 个。  民警:你可以走了。  我:为什么问这样的问题? 民警:深夜还在街上走,寒酸苦逼的样子,不是小偷就是程序员。”(注:看到有朋友评论说占几个字节跟具体的环境有关,学过C++的都知道,在C++这样的语言中确实取决于环境,但是在Java跟C#中不管什么环境都规定是4个字节,所以后边我们只讨论4个字节的情况)

  看完这个笑话,我脑袋立马将float、double等类型的字节长度闪了个遍。我知道float也占4个字节,但存储结构跟int是不一样的,并且表示范围也不一样。紧接着就出现了一个疑问,到底哪些int值是float不能表示的呢?如果你回答不了这个问题,那还是好好地了解一下吧,如果我说的不够清楚,请多查点其他的资料看一下。

  为什么有些int是float表示不了的呢?因为int与float同样占4个字节,float表示的范围又比int大并且还包含很多小数,那int的每个值都能被float表示就是不可能的事情了。在平时的编程中好像也没有感觉什么不对呀,这是为什么呢?先把这个问题留到后边,原理说清楚了再来回答这个问题。在文章的下边帖了一个进制转换程序,方便大家使用。

一. 小数十进制与二进制的转换

  二进制转换成十进制:跟整数转换一个原理,例如二进制11.11转换为十进制 1*21+1*20+1*2-1+1*2-2=3.75。

  十进制转换成二进制:整数部分不用说了,跟整数的十进制转成二进制没有区别。小数部分采用乘2取整的方式,比如3.75整数部分对应的二进制是11。小数部分0.75,先乘以2等于1.5,取1.5的整数部分。再用0.5(上次乘2的结果的小数部分)乘以2等于1.0,取1.0的整数部分,现在已经没有小数部分了,终止。0.75对应的二进制就是.11。

  所以3.75对应的二进制是11.11。注意这里的3.75和1.11只是浮点数十进制与二进制的不同表示形式,存储结构是一样的,因为本来就是同一个数。内存结构又是怎么样的呢,下边介绍。

二. float的存储结构

  float也是占32位,第一位是符号位(sign),符号位后边8位是指数(exponent),最后23位是尾数(mantissa)。

  float值的二进制表示形式是:signmantissa* 2exponent注意这个表达式是对应上述存储结构的二进制。

  符号位,表述浮点数的正或者负,0代表正,1代表负。

  指数位,实际也是有正负的,但是没有单独的符号位,在计算机的世界里,进位都是二进制的,指数表示的也是2的N次幂,8位指数表达的范围是0到255,而对应的实际的指数是-127到128。也就是说实际的指数等于指数位表示的数值减127。这里特殊说明,-127和+128这两个指数数值在IEEE当中是保留的用作多种用途的,这里就不多做介绍了,有兴趣的可以查阅其他资料。

  尾数位,只代表了二进制的小数点后的部分,小数点前的那位被省略了,当指数位全部为0时省略的是0否则省略的是1,为什么呢,看个例子:

  二进制11.11表示成指数形式是1.111*21,0.1111表示成指数形式是1.111*2-1。由此可见,正常情况下二进制的指数形式是肯定有一个1的,所以存储的时候直接省略。但是在指数位全部为0时,指数是-127,这个数字是有特殊含义的,在尾数全部为0时代表的数值是0,省略的那位是0,如果省略的是1那么0这个数字就没法用float表示了。

  

  结合例子理解一下

  那我们就看一下3.75的内存结构到底是什么样子的。首先转化成二进制形式11.11。转化成二进制指数形式1.111*21。由此我们可以得知尾数部分是111(将1省略掉了),不足23位的后边补0,指数部分是1+127=128,对应二进制10000000。所以存储结构就是1000000011100000000000000000000。

  反过来转换一下,比如某个float的存储结构是 11100000000000000000000,符号位是正的,指数位是128,实际的指数是128-127=1,尾数是111,再加上省略的那位就是1.111。所以对应的二进制指数形式是1.111*21,对应的二进制是11.11,对应的十进制是3.75。

,表示成指数形式是1.00000000000000000000000*223,对应的float的类型,尾数位全部为0,指数位是23+127=150,这样完全没有问题。假如一个int数值的二进制表示形式是1,表示成指数形式是1.000000000000000000000001*224,对应的float的类型尾数位是000000000000000000000001一共24位,这样就完全超出了float最多容纳23位尾数的能力。所以就不能正确表达这个int值了。由此也可以得出不能被float准确表达的最小int值是224+1。我们再将1000000000000000000000001的值加1,变成了1000000000000000000000010,这样变换为指数形式可以看出尾数又变为了23位,也就是说25位的二进制整数最后一位是0才能被float准确表示,每2个数就有一个不能被准确表示。如果是26位的二进制整数最后两位都是0才可以被float准确表达,每4个数就有3个不能被准确表示,以此类推。

  现在再来回答为什么在编程的过程中似乎没怎么引起注意,这是因为,我们平时用的数值基本都小于224+1=16777217。

下边是在网上找的一个二进制在线转换器,方便大家使用。

别在int与float上栽跟头的更多相关文章

  1. 别在int与float上栽跟头(转)

    源:http://www.cnblogs.com/luguo3000/p/3719651.html int与float是我们每天编程都用的两种类型,但是我们真的足够了解它们吗.昨天在博客园看到一个比较 ...

  2. BOOL,int,float,指针变量 与“零值”比较的if语句

    分别给出BOOL,int,float,指针变量 与“零值”比较的 if 语句(假设变量名为var) 解答: BOOL型变量:if(!var) int型变量: if(var==0) float型变量: ...

  3. 8、Python简单数据类型(int、float、complex、bool、str)

    一.数据类型分类 1.按存值个数区分 单个值:数字,字符串 多个值(容器):列表,元组,字典,集合 2.按可变不可变区分 可变:列表[],字典{},集合{} 不可变:数字,字符串,元组().bool, ...

  4. 实验与作业(Python)-02 Python函数入门与温度转换程序(函数、input、eval、int、float、列表)

    截止日期 实验目标 学会定义函数,使用函数.学会导入在某个文件中定义的函数. input获得值,然后通过eval或者int.float将其转换为相应的类型. 学会使用列表:访问列表.append.遍历 ...

  5. c++之常见数据类型(int,double,float,long double long long 与std::string之间)相互转换(含MFC的CString、含C++11新特性函数)

    --- 已经通过初步测试---- ------------------ 下面的是传统常见数据类型的转换(非c++11)---------------  std::string 与其他常用类型相互转换, ...

  6. 变量存储缓存机制 Number (int bool float complex)

    # ###变量存储的缓存机制(为了节省空间) #Number (int bool float complex) # (1) int -5~正无穷范围内 var1 = 18 var2 = 18 var1 ...

  7. 数据类型int、float、str、list、dict、set定义及常用方法汇总

    数据类型int:记录整数事物状态 可变不可变:值不可变类型,改变变量值实则是改变了变量的指向 int():功能:1.工厂函数, i = 5 <==> i = int(5) 2.强制类型转换 ...

  8. python 四种数值类型(int,long,float,complex)介绍

    Python支持四种不同的数值类型,包括int(整数)long(长整数)float(浮点实际值)complex (复数),本文章向码农介绍python 四种数值类型,需要的朋友可以参考一下. 数字数据 ...

  9. SQLServer int转float

    例: select 2/4  会得到0 改为 select 2/4.0 则会得到0.500000 也同时达到了int转float的效果

随机推荐

  1. HTML5 <iframe> 标签

    iframe 元素会创建包含另外一个文档的内联框架(即行内框架). 即页面中嵌入另外一个独立的页面使用iframe,熟悉src是嵌套的页面的路径地址,scrolling属性可以设置iframe的滚动条 ...

  2. CUDA2.4-原理之性能优化及浮点运算

    本部分来自于<大规模并行处理器编程实战>第六章.第七章.打算不再看这本书了,准备看<programming massively parallel processors 2nd> ...

  3. DAY65

    # 1.web应用# 2.CS和BS架构# 3.http协议# 特点: 1.接受请求正在处理# 2.请求处理完毕# 3.需要进行附加操作以完成请求# 4.服务器无法处理请求# 5.服务器处理请求出错# ...

  4. 微信小程序开发 [03] 事件、数据绑定和传递

    1.事件绑定 在微信小程序中,事件的绑定依附于组件,当事件触发时,就会执行事件对应的处理函数. 我们回到前几章中的例子,将index页面调整为首页(app.json中调整pages数组元素的顺序),此 ...

  5. office2016word 每次打开都有进度条问题 解决方式

      最佳答案   每次打开Office 2016都提示配置进度(包括Word.PPT.Excel等等Office产品都有这种现象),如图,先是显示“安装程序正在准备必要的文件”,接着显示“正在配置Mi ...

  6. TensorFlow(1):使用Docker镜像搭建TensorFlow环境

    1,关于TensorFlow TensorFlow 随着AlphaGo的胜利也火了起来. google又一次成为大家膜拜的大神了.google大神在引导这机器学习的方向. 同时docker 也是一个非 ...

  7. cleanCode[1]:有意义的命名

    为什么要有意义的命名: 我们都曾经说过有朝一日再回头清理那些糟糕的代码,然而最终总是弃之不顾.稍后等于永不,我们需要立即行动,写优雅的代码. 写代码的过程中,读占的比例很大,所以首先要让代码易读. 有 ...

  8. 20155318 《网络攻防》Exp3 免杀原理与实践

    20155318 <网络攻防>Exp3 免杀原理与实践 基础问题 杀软是如何检测出恶意代码的? 基于特征来检测:恶意代码中一般会有一段有较明显特征的代码也就是特征码,如果杀毒软件检测到有程 ...

  9. 总结 : C#事件理解

    要理解事件,首先必须理解委托!! 1.如果说委托是一个类型,那么事件就是一个对象! 2.事件的创建必须是借助某个委托类型来完成的! 3.也就是说,委托是事件的类型,事件本身是个对象!! 4.所以,事件 ...

  10. LoRa---数据包结构、跳频

    数据包结构  跳频扩频技术FHSS 人太懒,直接贴图,自己看!