黑马程序员技术交流社区

标题: float的精度 [打印本页]

作者: helloxiaoyu    时间: 2015-8-6 00:14
标题: float的精度
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?

作者: fmi110    时间: 2015-8-6 09:12
好细心,我就发现不了这样的问题{: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
作者: JustForYou    时间: 2015-8-6 10:01
这个问题好有深度啊
作者: 王连正    时间: 2015-8-6 11:32
真的好厉害
作者: helloxiaoyu    时间: 2015-8-6 14:17
fmi110 发表于 2015-8-6 09:12
好细心,我就发现不了这样的问题
不过导致这个问题出现应该是二进制表示的方法导致的  网上找了答 ...

非常感谢
作者: godboy001    时间: 2015-8-6 16:12
float的精度本来就不高的,double稍微高一些
作者: 陈化身1    时间: 2015-8-6 19:37
向下转型
作者: loneyyao    时间: 2015-8-6 19:44
太厉害了  我还得慢慢看




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2