资源预览内容
第1页 / 共3页
第2页 / 共3页
第3页 / 共3页
亲,该文档总共3页全部预览完了,如果喜欢就下载吧!
资源描述
别在 int 与 float 上栽跟头 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 的整数部分 1。再用0.5(上次乘 2 的结果的小数部分)乘以 2 等于 1.0,取 1.0 的整数部分 1,现在已经没有小数部分了,终止。0.75 对应的二进制就是.11。所以 3.75 对应的二进制是 11.11。注意这里的 3.75 和 1.11 只是浮点数十进制与二进制的不同表示形式,存储结构是一样的,因为本来就是同一个数。内存结构又是怎么样的呢,下边介绍。二. float 的存储结构float 也是占 32 位,第一位是符号位(sign ),符号位后边 8 位是指数(exponent ),最后 23 位是尾数(mantissa)。float 值的二进制表示形式是:sign* mantissa* 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。所以存储结构就是01000000011100000000000000000000。反过来转换一下,比如某个 float 的存储结构是01000000011100000000000000000000,符号位是正的,指数位是128,实际的指数是 128-127=1,尾数是 111,再加上省略的那位就是1.111。所以对应的二进制指数形式是 1.111*21,对应的二进制是 11.11,对应的十进制是 3.75。到这里我们就可以看出,实际上尾数决定了浮点数的精度,尾数只有 23位,加上省略的那位就是 24 位。如果一个 int 类型的值小于 224,那么 float是完全可以表示的。如果 int 类型大于 224 就不一定能表示了。假如一个 int 数值的二进制表示形式是 100000000000000000000000,表示成指数形式是1.00000000000000000000000*223,对应的 float 的类型,尾数位全部为0,指数位是 23+127=150,这样完全没有问题。假如一个 int 数值的二进制表示形式是 1000000000000000000000001,表示成指数形式是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。
网站客服QQ:2055934822
金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号