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

 找回密码
 加入黑马

QQ登录

只需一步,快速开始

© 冯佩 中级黑马   /  2013-2-17 12:27  /  2090 人查看  /  10 人回复  /   0 人收藏 转载请遵从CC协议 禁止商业使用本文

本帖最后由 冯佩 于 2013-2-20 15:11 编辑

public class Test
{
     public static void main(String[] args)
     {
         double item = 1;
         double sum=0;
         while(item != 0)
         {
             sum += item;
             item -= 0.1;
          }
          System.out.println("sum="+sum);
      }
}
以上是对1+0.9+0.8+...+0.1进行求和的一种代码编写方式,请分析打印不出结果的原因。

评分

参与人数 1技术分 +1 收起 理由
Rancho_Gump + 1

查看全部评分

10 个回复

倒序浏览
本帖最后由 王昕 于 2013-2-17 13:23 编辑

经过调试发现,-0.1之后,item就变成了0.90000000000000002,每步的结果都有误差,不是刚好减0.1,所以item一直都不等于0,所以一直循环。

评分

参与人数 1技术分 +1 收起 理由
Rancho_Gump + 1

查看全部评分

回复 使用道具 举报
public class Test
{
     public static void main(String[] args)
     {
         double item = 1;
         double sum=0;
         while(item != 0)  //这段代码在河的时候出现了死循环,所以JVM无法执行输出语句 System.out.println("sum="+sum);

         {
             sum += item;
             item -= 0.1;
          }
          System.out.println("sum="+sum);
      }
}

评分

参与人数 1技术分 +1 收起 理由
Rancho_Gump + 1

查看全部评分

回复 使用道具 举报
因为这个循环永远不会结束
回复 使用道具 举报
while(item != 0)
         {
             sum += item;
             item -= 0.1;
          }
由于你用的是double型数据,当item=0.8自减到0.7时得到的是item=0.7000000000000001       
你调试一下,会发现不会出现item=0.00000000000000的情况

评分

参与人数 1技术分 +1 收起 理由
Rancho_Gump + 1

查看全部评分

回复 使用道具 举报
本帖最后由 康乐 于 2013-2-17 17:02 编辑

由于在-0.1时结果不够精确,所以出现了死循环。调试时会发现item在减了0.1几次以后结果就会不够精确。

java中floa或者double运算时可能会丢失精度,因为十进制小数转换成二进制数时表示可能不够精确,就像十进制系统中能不能准确表示出1/3,同样二进制系统也无法准确表示1/10。float和double只能用来做科学计算或者是工程计算,在精确的计算中我们要用java.math.BigDecimal。通常用的构造方法是以下两个:
BigDecimal(double val)
BigDecimal(String val)
第一个构造方法虽然用起来方便但是有一定的不可预知性,具体在API中有介绍
所以如果需要精确计算,最好用String来够造BigDecimal。
需要先将两个浮点数转为String,然后够造成BigDecimal,在其中一个上调用方法,传入另一个作为参数,
然后把运算的结果(BigDecimal)再转换为浮点数。

主函数总这样写
  1. double item = 1;
  2. double sum=0;
  3. while(item != 0)
  4. {
  5. sum += item;
  6. BigDecimal bdItem = new BigDecimal(Double.toString(item));
  7. BigDecimal bd = new BigDecimal("0.1");
  8. item = bdItem.subtract(bd).doubleValue();

  9. }
  10. System.out.println("sum="+sum);
复制代码

评分

参与人数 1技术分 +1 收起 理由
Rancho_Gump + 1

查看全部评分

回复 使用道具 举报
胥文 中级黑马 2013-2-17 22:01:35
7#
public static void main(String[] args) {
               
                double temp =1;
                double sum = 0;
                while(temp !=0)
                {
                        sum+=temp;
                        temp = temp-0.1;
                        //使用给定的模式(小数保留一位)创建一个DecimalFormat对象
                        DecimalFormat df = new DecimalFormat(".0");
                        //将temp按照指定的格式格式化之后,在转化成Double
                        temp = Double.valueOf(df.format(temp));
                        System.out.println(temp);
                       
                }
               
                System.out.println(sum);

        }

}
已经验证,这样就是你要的结果
回复 使用道具 举报
黄玉昆 黑马帝 2013-2-17 23:13:26
8#
你试试这段代码,应该是没问题的了:
  1. public class Test
  2. {
  3.      public static void main(String[] args)
  4.      {
  5.          int item = 10;
  6.          float sum=0f;
  7.          while(item != 0)
  8.          {
  9.              sum += item;
  10.              item -= 1;
  11.           }
  12.           System.out.println("sum=" + (sum/10));
  13.       }
  14. }
复制代码
这里的float的范围要大于int,所以是可以进行sum+=item语句的。但是不能将sum定义为int,否则打印结果为int型了。
回复 使用道具 举报
冯佩 中级黑马 2013-2-18 03:37:31
9#
感谢各位的参与,在循环中请尽量不要使用浮点值来比较值是否相等,因为浮点值都是某些值的近似值,所以不能确保item会变成真正的0,从表面上看,这个循环似乎没问题,但实际上它是一个无限循环。
回复 使用道具 举报
都很牛,楼主可以变成已解决了
回复 使用道具 举报
       double item = 1;
         double sum=0;
         while(item != 0)
         {
             sum += item;
             item -= 0.1;
          }
          System.out.println("sum="+sum);
我是这样理解的:
java中switch()中不可使用浮点数来判断条件,同理while中也不会使用浮点数来判断条件,所以如果在while中判断条件的数值类型应该用整型
回复 使用道具 举报
您需要登录后才可以回帖 登录 | 加入黑马