问题背景:
在作业中计算圆的面积时,运算表达式中含有double类型,代码如下:
int r = 45;
double pi = 3.14;
double c = 2 * pi * r;
double s = pi * r * r;
System.out.println("梳妆镜的周长是" + c + "厘米,面积是" + s + "平方厘米");
结果却得到这样的答案:

本来正确的计算结果应该是6358.5,后面有几位小数肯定是不正确的,后来想起来这是double类型在运算的时候经常会出现的精度丢失问题。最终答案我需要保留一位小数,后来发现java中有几个办法能够满足我的需求。
解决办法:
BigDecimal
这种方法需要导入 java.math.BigDecimal 和 java.math.RoundingMode ,方法是将double类型数据转换成BigDecimal类型,接着通过setScale的方法定义想要保留的小数位数以及四舍五入。举例我要保留一位小数,代码如下:
int r = 45;
double pi = 3.14;
double c = 2 * pi * r;
double s = pi * r * r;
BigDecimal bd = BigDecimal.valueOf(s);
bd = bd.setScale(1, RoundingMode.HALF_UP);
s = bd.doubleValue();
System.out.println("梳妆镜的周长是" + c + "厘米,面积是" + s + "平方厘米");
setScale( ,)方法逗号前是保留的位数,逗号后是四舍五入的定义,将操作后的结果赋给一个变量bd,由于结果是BigDecimal类型,所以我们用.doubleValue( ) 方法转换成double类型赋给s,这样就成功保留了一位小数。

DecimalFormat
这个方法和第一个类似,需要导入 java.text.DecimalFormat,需要实例化一个DecimalFormat对象,并设置保留的小数位数,代码如下:
int r = 45;
double pi = 3.14;
double c = 2 * pi * r;
double s = pi * r * r;
DecimalFormat df = new DecimalFormat("0.0");
s = Double.parseDouble(df.format(s));
System.out.println("梳妆镜的周长是" + c + "厘米,面积是" + s + "平方厘米");
由于该方法结果是String字符串类型,所以用Double.parseDouble方法将字符串转换成double类型,结果也成功保留了一位小数。

String.format
这个方法比较简单,直接上代码:
int r = 45;
double pi = 3.14;
double c = 2 * pi * r;
double s = pi * r * r;
String str = String.format("%.1f", s);
s = Double.parseDouble(str);
System.out.println("梳妆镜的周长是" + c + "厘米,面积是" + s + "平方厘米");
用String.format定义需要保留的位数和传入的double数据得到字符串类型,然后再转换成double类型即可。

(PS:如果遇到如2.295需要保留两位,结果可能会变成2.3,如果需要补全0可以再使用DecimalFormat实例化一个new DecimalFormat("0.00")然后用.format方法即可。)
4.数学运算
这是直接通过数学运算的土办法,但是很简单也很好理解,代码如下:
int r = 45;
double pi = 3.14;
double c = 2 * pi * r;
double s = pi * r * r;
int s1 = (int)(s * 10);
s = s1 * 0.1;
System.out.println("梳妆镜的周长是" + c + "厘米,面积是" + s + "平方厘米");
通过乘以10将小数点向右移一位,然后强转成int类型舍掉小数点右边的小数位,之后再通过乘以0.1将小数点向左移一位重新赋值给s,也能够得到正确的结果。
