A股上市公司传智教育(股票代码 003032)旗下技术交流社区北京昌平校区

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© helloxiaoyu 中级黑马   /  2015-8-6 00:14  /  616 人查看  /  7 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

class D{
         public static void main(String[] args){
                 byte a=120;
                 short b=256;
                 int c=2200;
                 long d=122121L;
                 float f;
                 double g=0.114468547432;
                 a=(byte)b;
                 c=(int)d;
                 f=(float)g;
                 System.out.println("a="+a);
                 System.out.println("b="+b);
                 System.out.println("c="+c);
                 System.out.println("d="+d);
                 System.out.println("f="+f);
                 System.out.println("g="+g);
        }
}
为什么输出的 f=0.114468545?
当 g=0.12345678987654321 时, 输出的 f=0.12345679?

7 个回复

倒序浏览
好细心,我就发现不了这样的问题{:3_65:}
不过导致这个问题出现应该是二进制表示的方法导致的  网上找了答案  看看
这是因为,IEEE标准的 float 类型用 23 bit 来表示浮点数的小数部分。
极限情况下(这时没有使用隐含的高位),这里所能表示的 10 进制的精度是 log10(2^23) = 6.92...
所以最小也能保持 6 位的精度。
============================

至于楼主所说的情形,是因为你的那种情况不是极限情形。
实际上,浮点数的存储形式是类似于:  
   数字 * 2^(幂)
的形式的。
而 123456.789098765678
  表示成 1.111 0001 0010 0000 0110 0101 * 2^(16) 的-- *前的是2进制。
不信可以自己算算,将那个 2 进制转成 10 进制,然后 16次 乘 2 ,看结果是否如此。
这里小数点前的 1 是隐含的,实际存储的只有小数点后的数,就是 23 bit。

可以说,能够保留到 10 位完全是数字本身的结构,比较幸运了。
你甚至试试
float x = 0.000000000931322574615478515625; // 2^-30
然后用 printf("%.35f\n", x);看看,这里甚至完全保持原来的精度,
这就是数字本身的特殊结构所导致的。
再试试 999989.98 看看,精度还有没有 10位了。
==========================================

实际上,绝大部分情况(除了很接近0的数),都是使用 一位隐含的高位 的,
这时的精度是 log10(2^24) = 7.22
所以也有的书也说 float 的精度是 7 位--- 比如我刚学 C 时所看的那本……
http://bbs.csdn.net/topics/60084709
回复 使用道具 举报
这个问题好有深度啊
回复 使用道具 举报
真的好厉害
回复 使用道具 举报
fmi110 发表于 2015-8-6 09:12
好细心,我就发现不了这样的问题
不过导致这个问题出现应该是二进制表示的方法导致的  网上找了答 ...

非常感谢
回复 使用道具 举报
float的精度本来就不高的,double稍微高一些
回复 使用道具 举报
向下转型
回复 使用道具 举报
太厉害了  我还得慢慢看
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马