您的当前位置:首页正文

Double精度控制lwy

来源:帮我找美食网
Double精度控制

李雯燕

问题位置:Logic Java P245:上机2 变量、数据类型和运算符·第三部分作业·第2题 题目:编写一个程序,根据矩形的长(1.9m)和宽(0.3m),计算矩形的面积和周长。

提示:计算面积的公式:面积 = 长 * 宽 计算周长的公式:周长 = 2 * ( 长 + 宽 ) 实现代码: public class Class1 { public static void main(String[] args) { double a = 1.9;//矩形的长 double b = 0.3;//矩形的宽 double s = a * b;//计算矩形的面积 double l = 2 * ( a + b );//计算矩形的周长 System.out.println(\"矩形面积是:\"+ s +\"平方米\");//输出矩形面积 System.out.println(\"矩形周长是:\"+ l +\"米\");//输出矩形周长 } } 输出结果: 矩形的面积是:0.57平方米 矩形的周长是:4.3999999999999995米 出现问题,矩形的周长应该是4.4米。

原因:

实型数据在内存中存在的时候是以指数形式储存的,例如float类型有4字节,一般前三个字节储存小数部分,后一个字节储存指数部分。

比如380在内存中的储存是小数部分:0.38,指数部分:3,即0.38*103,前面的是小数,在转换为二进制数时有时会出现误差,小数转二进制数部分,有可能出现无限循环:

以0.375转换为二进制数为例: 小数乘2 纯小数部分 整数部分 2*0.375=0.750 0.750 0 2*0.750=1.5 0.5 1 2*0.5=1.0 0 1 结果就为0.011(从上到下),纯小数为0终止。否则一直进行下去。

所以实型数据的储存并不准确。但double是8个字节,一般前7个字节(56位)用来储存小数部分,即使在转换的时候出现无限循环,那也是二进制的第56位了,所以误差极小,一般的数据都能准确的表示出来。

以我们这道题的结果4.4为例,将其转换成二进制数: 首先在内存中存储的小数部分为0.44,指数部分为1。 小数乘2 纯小数部分 整数部分 2*0.44=0.88 0.88 0 2*0.88=1.76 0.76 1

2*0.76=1.52 2*0.52=1.04 2*0.04=0.08 2*0.08=0.16 2*0.16=0.32 2*0.32=0.64 2*0.64=1.28 2*0.28=0.56 2*0.56=1.12 2*0.12=0.24 2*0.24=0.48 2*0.48=0.96 2*0.96=1.92 2*0.92=1.84 2*0.84=1.68 2*0.68=1.36 2*0.36=0.72 2*0.72=1.44 2*0.44=0.88 „„

0.52 0.04 0.08 0.16 0.32 0.64 0.28 0.56 0.12 0.24 0.48 0.96 0.92 0.84 0.68 0.36 0.72 0.44 0.88

1 1 0 0 0 0 1 0 1 0 0 0 1 1 1 1 0 1 0

转换操作陷入无限循环,结果是0.01110000101000111101。超出56位的部分就会被抛弃,所以造成表示不准确的情况发生。所以在这道题目中,得到了一个不准确的结果。

解决办法:

1、 使用DecimalFormat类对数字格式进行限制的方法。 import java.text.DecimalFormat;//引入java.text包里DecimalFormat类 public class Class1 { public static void main(String[] args) { double a = 1.9;//矩形的长 double b = 0.3;//矩形的宽 double s = a * b;//计算矩形的面积 double l = 2 * ( a + b );//计算矩形的周长 System.out.println(\"矩形的面积是:\"+ s +\"平方米\");//输出矩形面积 DecimalFormat df=new DecimalFormat(\"0.00\"); //设置格式为保留小数点后两位 System.out.println(\"矩形的周长是:\"+df.format(l)+\"米\");//格式控制后输出矩形周长 } }

输出结果: 矩形的面积是:0.57平方米 矩形的周长是:4.40米 建议:该方法是比较常用的解决此类问题的手段,但是在学生学习Java编程初期,没有接触过类和对象的

概念,对此方法不容易理解和记忆。如果使用的话,需要死记硬背,建议在学生学习完类和对象概念之后再回过头来介绍该方法。

2、 使用NumberFormat类对数字精度进行限制的方法。 import java.text.NumberFormat;//引入java.text包里NumberFormat类 public class Class1 { public static void main(String[] args) { double a = 1.9;//矩形的长 double b = 0.3;//矩形的宽 double s = a * b;//计算矩形的面积 double l = 2 * ( a + b );//计算矩形的周长 System.out.println(\"矩形的面积是:\"+ s +\"平方米\");//输出矩形面积 NumberFormat nf=NumberFormat.getInstance();//获取NumberFormat类对象 nf.setMaximumFractionDigits(2);//设置小数位至多2位,多者四舍五入 System.out.println(\"矩形的周长是:\"+nf.format(l)+\"米\");//格式控制后输出矩形周长 } } 输出结果: 矩形的面积是:0.57平方米 矩形的周长是:4.4米 建议:该类用法比较灵活,可以细致定义整数位小数位至多至少保留的精度,但是在学生学习Java编程初期,这个类的用法对学生而言太过复杂,容易让学生产生畏难心理,所以不建议介绍。

3、 使用System.out.printf方法对输出格式进行限制的方法。 public class Class1 { public static void main(String[] args) { double a = 1.9;//矩形的长 double b = 0.3;//矩形的宽 double s = a * b;//计算矩形的面积 double l = 2 * ( a + b );//计算矩形的周长 System.out.println(\"矩形的面积是:\"+ s +\"平方米\");//输出矩形面积 System.out.printf(\"矩形的周长是:%.2f米\\n\", l); //格式控制后输出矩形周长 } } 输出结果: 矩形的面积是:0.57平方米 矩形的周长是:4.40米 建议:Java中的printf方法和C语言中的用法一致,操作步骤简单,并且没有涉及到类和对象的概念,只需要向学生简单介绍“转换字符串”的概念即可,所以建议学习Java的初期使用这种方法去控制Double类型的精度。

因篇幅问题不能全部显示,请点此查看更多更全内容

Top