java - 使用 BigDecimals 舍入区域
问题描述
我们正在做以下练习:TDD 面积计算。
我们编写了以下代码:
import java.math.*;
public class Calculator{
public double getTotalArea(Triangle triangle){
double area = triangle.base*triangle.height/2;
System.out.println("getTotalArea of triangle: "+area);
return area;
}
public double getTotalArea(Square square){
double area = BigDecimal.valueOf(square.side*square.side).setScale(2,BigDecimal.ROUND_HALF_EVEN).doubleValue();
System.out.println("getTotalArea of square: "+area);
return area;
}
public double getTotalArea(Rectangle rectangle){
double area = rectangle.width*rectangle.height;
System.out.println("getTotalArea of rectangle: "+area);
return area;
}
public double getTotalArea(Circle circle){
double area = BigDecimal.valueOf(circle.radius*circle.radius*Math.PI).setScale(2,BigDecimal.ROUND_HALF_EVEN).doubleValue();
System.out.println("getTotalArea of circle: "+area);
return area;
}
public double getTotalArea(Shape ...shapes){
Calculator calc = new Calculator();
BigDecimal result= BigDecimal.ZERO;
for(Shape shape : shapes){
if(shape instanceof Triangle){
result = result.add(BigDecimal.valueOf(calc.getTotalArea(new Triangle(shape.base,shape.height))));
System.out.println("getTotalArea adding : "+result);
}
if(shape instanceof Square){
result=result.add(BigDecimal.valueOf(calc.getTotalArea(new Square(shape.side))));
System.out.println("getTotalArea adding : "+result);
}
if(shape instanceof Rectangle){
result=result.add(BigDecimal.valueOf(calc.getTotalArea(new Rectangle(shape.height,shape.width))));
System.out.println("getTotalArea adding : "+result);
}
if(shape instanceof Circle){
result=result.add(BigDecimal.valueOf(calc.getTotalArea(new Circle(shape.radius))));
System.out.println("getTotalArea adding : "+result);
}
}
System.out.println("getTotalArea of all shapes result: "+result+"\n\n");
return result.setScale(2,BigDecimal.ROUND_HALF_EVEN).doubleValue();
}
}
class Shape{
double base, height, side, width, radius;
}
class Triangle extends Shape{
Triangle(double base, double height){
this.base=base;
this.height=height;
}
}
class Square extends Shape{
Square(double side){
this.side=side;
}
}
class Rectangle extends Shape{
Rectangle(double height, double width){
this.height=height;
this.width=width;
}
}
class Circle extends Shape{
Circle(double radius){
this.radius=radius;
}
}
我们想了解为什么在所有形状的 getTotalArea 方法中存在舍入困难。例如,让我们看看以下跟踪:
getTotalArea of square: 1425.6
getTotalArea of square: 1425.6
getTotalArea adding : 1425.6
getTotalArea of circle: 31.92
getTotalArea adding : 1457.52
getTotalArea of all shapes result: 1457.52
expected:<1457.53> but was:<1457.52>
看起来当有正方形和/或圆形时,该方法输出的数字与预期的数字不同。我们认为这是因为圆形和方形方法给出了一个已经四舍五入的结果。
但是,测试需要将圆形和方形结果四舍五入到小数点后两位。例如,如果我们将方法更改如下:
public double getTotalArea(Circle circle){
double area = circle.radius*circle.radius*Math.PI;
//double area = BigDecimal.valueOf(circle.radius*circle.radius*Math.PI).setScale(2,BigDecimal.ROUND_HALF_EVEN).doubleValue();
System.out.println("getTotalArea of circle: "+area);
return area;
}
测试输出:
getTotalArea of circle: 28.274333882308138
expected:<28.27> but was:<28.274333882308138>
此外,我们尝试使用字符串对结果进行四舍五入:
import java.math.*;
public class Calculator{
public double getTotalArea(Triangle triangle){
double area = triangle.base*triangle.height/2;
System.out.println("getTotalArea of triangle: "+area);
return area;
}
public double getTotalArea(Square square){
double area = BigDecimal.valueOf(square.side*square.side).setScale(2,BigDecimal.ROUND_HALF_EVEN).doubleValue();
System.out.println("getTotalArea of square: "+area);
return area;
}
public double getTotalArea(Rectangle rectangle){
double area = rectangle.width*rectangle.height;
System.out.println("getTotalArea of rectangle: "+area);
return area;
}
public double getTotalArea(Circle circle){
double area = BigDecimal.valueOf(circle.radius*circle.radius*Math.PI).setScale(2,BigDecimal.ROUND_HALF_EVEN).doubleValue();
System.out.println("getTotalArea of circle: "+area);
return area;
}
public double getTotalArea(Shape ...shapes){
Calculator calc = new Calculator();
BigDecimal result= BigDecimal.ZERO;
for(Shape shape : shapes){
if(shape instanceof Triangle){
result = result.add(BigDecimal.valueOf(calc.getTotalArea(new Triangle(shape.base,shape.height))));
System.out.println("getTotalArea adding : "+result);
}
if(shape instanceof Square){
result=result.add(BigDecimal.valueOf(calc.getTotalArea(new Square(shape.side))));
System.out.println("getTotalArea adding : "+result);
}
if(shape instanceof Rectangle){
result=result.add(BigDecimal.valueOf(calc.getTotalArea(new Rectangle(shape.height,shape.width))));
System.out.println("getTotalArea adding : "+result);
}
if(shape instanceof Circle){
result=result.add(BigDecimal.valueOf(calc.getTotalArea(new Circle(shape.radius))));
System.out.println("getTotalArea adding : "+result);
}
}
System.out.println("getTotalArea of all shapes result: "+result+"\n\n");
String s = String.valueOf(result.doubleValue());
System.out.println("s: "+s);
System.out.println("s.indexOf(\".\"): "+s.indexOf("."));
String threeDecimals = s.substring(0,s.length() - s.indexOf(".") >= 4 ? s.indexOf(".")+4 : s.length());
double number = Double.parseDouble(threeDecimals);
String decimalPart = threeDecimals.substring(threeDecimals.indexOf(".")+1);
if(decimalPart.length() > 2 && Character.getNumericValue(threeDecimals.charAt(threeDecimals.length()-1)) > 5){
number = number+0.01;
}
s = String.valueOf(number);
String twoDecimals = s.substring(0,s.length() - s.indexOf(".") >= 3 ? s.indexOf(".")+3 : s.length());
return Double.parseDouble(twoDecimals);
}
}
class Shape{
double base, height, side, width, radius;
}
class Triangle extends Shape{
Triangle(double base, double height){
this.base=base;
this.height=height;
}
}
class Square extends Shape{
Square(double side){
this.side=side;
}
}
class Rectangle extends Shape{
Rectangle(double height, double width){
this.height=height;
this.width=width;
}
}
class Circle extends Shape{
Circle(double radius){
this.radius=radius;
}
}
测试的痕迹是:
getTotalArea of square: 7439.73
getTotalArea of square: 7439.73
getTotalArea adding : 7439.73
getTotalArea of circle: 12722.91
getTotalArea adding : 20162.64
getTotalArea of all shapes result: 20162.64
s: 20162.64
s.indexOf("."): 5
res: 20162.64
因此,当有正方形和圆形时,看起来我们很难对区域进行四舍五入。
我们怎样才能正确地舍入它?
我们已经阅读:
解决方案
要四舍五入到小数位,请执行 Math.ceil(area * 100) / 100; 这将乘以 100 以确保保留 2 位小数,然后除以将它们返回到正确的位置。Math.ceil() 四舍五入。
推荐阅读
- excel - Convert stock transactions into daily holdings in Excel
- javascript - using uibModal in angularJS v1.48 applcation
- dart - Dart - Hide method from parent class / call private method from parent class
- javascript - handle find property in array if undefined
- javascript - Uncaught TypeError: downloadButton is null
- javascript - Change List of objects in position using map for Reactjs
- python - Pytest在导入模块时需要指定文件夹项目
- python - 如何使用 Python 和 Selenium 将多个文件上传到网站?
- r - 方差分析公式无法识别我的列标题
- javascript - 悬停按钮时更改多个样式属性