抱歉我用了一个这么“二”的题目,不过二点就二点吧,希望内容还不算太二。
其实学习过编程的同学,都对这三个东西再熟悉不过了。int,又称作整型,在.net中特指的是Int32,为32位长度的有符号整型变量。float,单精度浮点数,32位长度,1位符号位,8位指数位与23位数据位,在.net中又称为Single。double,64位长度的双精度浮点数,1位符号位,11位指数位,52位数据位。它们互相的关系就是:int可以稳式转换成float和double,float只能强制转换成int,但是可以隐式转换成double,double只能强制转换成float和int。
在说明问题之前,还很有必要温习一下计算机组成原理时学习到的一些知识,就是二进制补码表示以及浮点数表示。我想把一个十进制转化为二进制的方法已经不用多费唇舌,只不过为了计算方便以及消除正零与负零的问题,现代计算机技术,内存里存的都是二进制的补码形式,当然这个也没什么特别的,只不过有某些离散和点,需要特殊定义而已,比如-(2^31),这个数在int的补码里表示成1000…(31个零),这个生套补码计算公式并不能得到结果(其实不考虑进位的话还真是这个结果,但是总让人感觉很怪)。再者,浮点数,其实就是把任何二进制数化成以0.1....开头的科学计数法表示而已。

废话说完,这就出现了几个问题,而且是比较有意思的问题。

1 int i = Int32.MaxValue;
2 float f = i;
3 int j = (int)f;
4 bool b = i == j;

这里的b,是false。刚才这个操作,如果我们把float换成long,第一次进行隐式转换,第二次进行强制转换,结果将会是true。乍一看,float.MaxValue是比int.MaxValue大了不知道多少倍的,然而这个隐式转换中,却造成了数据丢失。int.MaxValue,这个值等于2^31-1,写成二进制补码形式就是01111…(31个1),这个数,在表示成float计数的科学计数法的时候,将会写成+0.1111…(23个1)*2^31,对于那31个1,里面的最后8个,被float无情的抛弃了,因此,再将这个float强制转换回int的时候,对应的int的二进制补码表示已经变成了0111…(23个1)00000000,这个数与最初的那个int相差了255,所以造成了不相等。
那么提出另一个问题,什么样的int变成float再变回来,和从前的值相等呢?这个问题其实完全出在那23位float的数据位上了。对于一个int,把它写成二进制形式之后,成为了个一32个长度的0、1的排列,对于这个排列,只要第一个1与最后一个1之前的间距,不超过23,那么它转换成float再转换回来,两个值就会相等。这个问题是与大小无关的,而且这个集合在int这个全集下并不连续。

1 double d = 0.6;
2 float f = (float)d;
3 double d2 = f;
4 bool b = d == d2;

这里的b,也是false。刚才这个操作,如果开始另d等于0.5,结果就将会是true。乍一看,0.6这个数这么短,double和float都肯定能够表示,那么转换过去再转换回来,结果理应相等。其实这是因为我们用十进制思考问题太久了,如果我们0.6化成二进制小数,可以发现得到的结果是0.10011001……(1001循环)。这是一个无限循环小数。因此,不管float还是double,它在存储0.6的时候,都无法完全保存它精确的值(计算机不懂分数,呵呵),这样的话由于float保存23位,而double保存52位,就造成了double转化成float的时候,丢失掉了一定的数据,非再转换回去的时候,那些丢掉的值被补成了0,因此这个后来的double和从前的double值已经不再一样了。
这样就又产生了一个问题,什么样的double转换成float再转换回来,两个的值相等呢?其实这个问题与刚才int的那个问题惊人的相似(废话,都和float打交道,能不相似么),只不过我们还需要考虑double比float多了3位的指数位,太大的数double能表示但float不行。
还有一个算是数学上的问题,什么样的十进制小数,表示成二进制不是无限小数呢?这个问题可以说完全成为数学范畴内的问题了,但是比较简单,答案也很明显,对于所有的最后一位以5结尾的十进制有限小数,都可以化成二进制的有限小数(虽然这个小数可能长到没谱)。
最后,一个有意思有问题,刚才说过0.6表示成为二进制小数之后,是0.1001并且以1001为循环节的无限循环小数,那么在我们将它存成浮点数的时候,一定会在某个位置将它截断(比如float的23位和double的52位),那么真正存在内存里的这个二进制数,转化回十进制,到底是比原先的十进制数大呢,还是小呢?答案是It depends。人计算十进制的时候,是四舍五入,计算机再计算二进制小数也挺简单,就是0舍1入。对于float,要截断成为23位,假如卡在24位上的是1,那么就会造成进位,这样的话,存起来的值就比真正的十进制值大了,如果是0,就舍去,那么存起来的值就比真正的十进制值小了。因此,这可以合理的解释一个问题,就是0.6d转换成float再转换回double,它的值是0.60000002384185791,这个值是比0.6大的,原因就是0.6的二进制科学计数法表示,第24位是1,造成了进位。

到了这里,仍然有一事不解,就是对于浮点数,硬件虽然给予了计算上的支持,但是它与十进制之间的互相转换,到底是如何做到的呢,又是谁做的呢(汇编器还是编译器)。这个东西突出体现在存在内存里的数明显实际与0.6不等,但是无论哪种语言,都能够在Debug以及输入的时候,将它正确的显示成0.6提供给用户(程序员),最好的例子就是double和ToString方法,如果我写double d=0.59999999999999999999999999999,d.ToString()给我的是0.6。诚然,对于double来说,我写的那个N长的数与0.6在内存里存的东西是一样的,但是计算机,又如果实现了将一个实际与0.6不相等的数变回0.6并显示给我的呢?关于这个问题,欢迎大家讨论并请高手指教一二。

转载于:https://www.cnblogs.com/wodehuajianrui/archive/2009/03/18/1415173.html

int, float, double之间不得不说的故事相关推荐

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

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/github_33873969/article/details/78040129 从学了C语言之后,一 ...

  2. 云图说|ROMA演进史:一个ROMA与应用之间不得不说的故事

    阅识风云是华为云信息大咖,擅长将复杂信息多元化呈现,其出品的一张图(云图说).深入浅出的博文(云小课)或短视频(云视厅)总有一款能让您快速上手华为云.更多精彩内容请单击此处. 摘要: 华为云ROMA源 ...

  3. Python:int,float,str之间的转换

    文章目录 数据类型转换 其它数据转换的内置函数 数据类型转换 主要介绍int,float,str之间的相互转换,转换方向见上图. 其它数据转换的内置函数 python各种类型转换-int,str,ch ...

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

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

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

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

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

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

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

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

  8. int float double char 所占字节数及数字范围之间的关系

    原码就是取 绝对值.反码是原码取反.补码是反码+1. int int 在32/64位系统中占4个字节,一个字节能含八位二进制数字0/1,四个字节含32位,所以表示的数的范围为-(2的31次方-1)到( ...

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

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

最新文章

  1. 未来的程序员面临着怎样的职业变化
  2. qps是什么意思_面试官:说说你之前负责的系统,QPS 能达到多少?
  3. java怎么不安装到c盘的教程,帮您设置win10系统安装不了java的详细步骤
  4. 【机器视觉】 fuzzy_measure_pairing算子
  5. 方根法公式_仓储管理笔记之库存分析法:ABC分析法、区域合并法......
  6. Redis常见面试题5 -- 持久化方式之RDB(快照模式)
  7. vs2015 vs2017 编译zlib库
  8. DES, TripleDES and BlowFish in Silverlight
  9. MySQL当查询的时候有多个结果,但需要返回一条的情况用GROUP_CONCAT拼接
  10. python语言适用于哪些领域_Python用于哪些领域
  11. 【大规模图像检索的利器】Deep哈希算法介绍
  12. ruby写的BT种子解析器
  13. 编译器GCC的Windows版本 : MinGW-w64安装教程
  14. oracle 11g 01017,oracle 11G OEM 出现问题 ORA-01017: inv
  15. idea 如何查看jdk源码
  16. windows server2008 安装iscsi服务
  17. 【OKR案例合集】产品、研发、设计岗位的OKR案例合集
  18. 如何举报YouTube视频和评论
  19. 每日英语:China Bridge Collapse Raises Infrastructure Concerns
  20. 458、Java框架112 -【MyBatis - 一级缓存、二级缓存】 2020.12.28

热门文章

  1. c调用python第三方库_用 Python ctypes 来调用 C/C++ 编写的第三方库
  2. 在本地计算机无法启动windows audio,win10系统无法启动windowsaudio服务的操作步骤
  3. 五子棋人机对战_原生JS+Canvas实现五子棋游戏
  4. 你真的会读datasheet吗?
  5. MCU,RTOS,物联网之间的关系。
  6. 嵌入式驱动自学者的亲身感受,有什么建议?
  7. 调查了6万多名开发者后,我们发现了这些...
  8. 电路中的这些符号标识,你真的明白吗?
  9. java 控制 crt_secureCRT关闭连接自动关闭tomcat服务
  10. java 生成折线图_jfree jsp java 生成折线图(详解带jar)