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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© x378320002 中级黑马   /  2013-5-29 22:21  /  1124 人查看  /  8 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 x378320002 于 2013-5-30 20:06 编辑

今天碰到一个小问题,不明白原理,哪位基础很耗的童鞋给解答下
  1. class DEMO{
  2.         public static void main(String[] args) {
  3.                         System.out.println(2.00-1.10);
  4.                         System.out.println(2.00+1.10);
  5.                         System.out.println(2.00f-1.10f);
  6.         }
  7. }
复制代码
结果分别是,0.89999999999,3.1,0.9,为什么第一个不是0.9?
基础太薄弱了我

评分

参与人数 1技术分 +1 收起 理由
袁梦希 + 1 很给力!

查看全部评分

8 个回复

倒序浏览
亲,因为在电脑内存中是以二进制形式进行运算的!
回复 使用道具 举报
2.00和1.10 在java中是作为double类型识别的. 你看到3位,但在java语言中,是把这个数作为double型放到了64位的存储空间中进行计算的.

评分

参与人数 1技术分 +1 收起 理由
袁梦希 + 1 很给力!

查看全部评分

回复 使用道具 举报
本帖最后由 张俊迪 于 2013-5-29 23:53 编辑

java中的浮点数据类型float和double不能进行运算,因为他们算出来的数有可能与实际不符,不光是java这样,在其他很多语言中也出现这种问题,对于这个问题java提供了java.math.BigDecimal包通过BigDecimal这个类可以实现浮点数的加减乘除以及四舍五入,在这里我只说一个减法,其他的方法你可有上api文档中查看.
看我写的一个代码吧:
import java.math.BigDecimal;
public class Text4 {
        public static void main(String[] args) {
//        System.out.println((2.00-1.10));
                double d1=2.00,d2=1.10;//用你的数
                String s1=Double.toString(d1);//记住最好把这个数据类型转化为String类型,不只是double别的也一样
                String s2=Double.toString(d2);
                BigDecimal b1=new BigDecimal(s1);//将 BigDecimal 的字符串表示形式转换为 BigDecimal。用到构造函数BigDecimal(String val)
                BigDecimal b2=new BigDecimal(s2);
                double d=b1.subtract(b2).doubleValue();//这个地方的subtract方法就减法的意思,这可从api中查出,还有add(+)divide(/)multiply(*)算出的结果在转化//成原来数据类型就好了。
                System.out.println(d);
        }
}
其他的方法我就不说了,要是不明白我们还可以在讨论,看看Api应该能行,上面讲的很清楚

评分

参与人数 1技术分 +1 收起 理由
袁梦希 + 1 很给力!

查看全部评分

回复 使用道具 举报
张俊迪 发表于 2013-5-29 23:50
java中的浮点数据类型float和double不能进行运算,因为他们算出来的数有可能与实际不符,不光是java这样, ...

嗯,不明白是为什么浮点型的就算不准,我自己在掰扯掰扯吧,这个应该和浮点数存储形式有关吧
回复 使用道具 举报
刘勇强 发表于 2013-5-29 23:14
2.00和1.10 在java中是作为double类型识别的. 你看到3位,但在java语言中,是把这个数作为double型放到了64 ...

我知道啊,我是不知道为什么在64位空间就不准了?这个多少位没关系吧,应该是存储形式问题,我就是不知道这个是怎么存的
回复 使用道具 举报
x378320002 发表于 2013-5-30 12:05
嗯,不明白是为什么浮点型的就算不准,我自己在掰扯掰扯吧,这个应该和浮点数存储形式有关吧 ...

也许吧,我不懂
回复 使用道具 举报
这道题,曾经在论坛里出现过  我也纠结了半天
回复 使用道具 举报
本帖最后由 花心々小土豆 于 2013-5-30 22:55 编辑

先来简单想下,我们都知道十进制中1/3不可能用小数表示出来,同样十进制数0.1在二进制中也不能具体表示,在做运算过程中精度丢失导致的。
在复杂点的想,用乘2取整法将小数化为二进制数。举个例子:
0.5 = 1/2=2^(-1)
0.75 = 1/2 + 1/(2^2)=2^(-1)+2^(-2)=0.11
0.85 = 1/2 + 1/(2^2) + 1/(2^3)=2^(-1)+2^(-2)+2^(-3)
0.1 = 1/(2^4) + 1/(2^5) + 1/(2^8) + ...
如果还想往下想的话,因为:
float是32位的,其中尾数23位,第23位(从0位起算)永远为一,8位阶码(移码表示,余-127格式),第31位为符号位。
double是64位的,其中尾数52位,第52位(从0位起算)永远为一,11位阶码(移码表示,余-1023格式),第63位为符号位。
浮点数运算法则:1,对介;2,尾数求和;3,规格化;4,舍入;5,溢出判断。
这是计算机组成原理里的知识,我们上学期刚学过,看到有舍入的,就会有误差。有兴趣的各位可以找组成原理自己看看。我们只需要了解就行了,正如上面那哥们发的贴一样,Java中已经帮我们解决了这类误差问题,BigDecima类中封装好了。
其实那都不是什么意外的,不只是减法会有误差。System.out.println(0.1+0.1+0.1);这句输出的结果更可怕!!
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马