【发布时间】:2017-11-08 17:06:05
【问题描述】:
所以在编码方面我或多或少是个菜鸟。我正在为一门大学课程学习 java,我的一个练习要求我编写一个代码,使用左端点法、中点法和梯形法计算积分。
为此,我需要使用一个每次递增一步的 for 循环。我知道如何只使用双精度来做到这一点,但问题是,当我使用双精度数据类型运行计算时,它会给我带来舍入错误。阅读后(主要是查看其他堆栈溢出问题),我想我应该使用 BigDecimal 来消除舍入错误。
但是,使用 BigDecimal 会给我带来一大堆错误。据我所知,我不能使用普通运算符,例如 、== 等,因为 BigDecimal 不是原始数据类型。但是后来我不知道如何在仍然使用 BigDecimal 的同时进行递增的基本 for 循环。我在这里看到的另一件事建议使用 Commons-math? (第二个答案)
https://stackoverflow.com/questions/16707397/whats-wrong-with-this-simple-double-calculation#=
我不知道如何使用它,因为据我所知,它与简单的旧 import java.lang.Math 不相似。
所以我想我的问题是,我怎样才能让我的代码在 for 循环中使用 BigDecimal 工作,并且通常将数字比较在一起,或者我怎样才能使用 Common-Math 来完全避免舍入错误?
这是我的代码:
import java.util.Scanner;
import java.lang.Math;
import java.math.BigDecimal;
public class IntegrationMethods{
//calculates the value of the function f(x)=x^2
public static BigDecimal f(BigDecimal x){
return x.multiply(x);
}
//uses a, b and N as arguments, calculates sum of integral using left
endpoint rule
public static BigDecimal leftEndpoint(BigDecimal a, BigDecimal b,
BigDecimal n){
BigDecimal h = (b.subtract(a)).divide(n);
sum = new BigDecimal("0");
i = new BigDecimal("0");
for(i.compareTo(n)<=0;){
sum = sum.add(h.multiply(f(a.add(h.multiply(i-1)))));
i = i.add(new BigDecimal(1));
}
return sum;
}
public static BigDecimal midpoint(BigDecimal a, BigDecimal b, BigDecimal
n){
BigDecimal h = (b.subtract(a)).divide(n);
BigDecimal sum = 0.0;
for(BigDecimal i=0.0; i<n; i++){
BigDecimal x1 = a.add(h.multiply(i));
BigDecimal x2 = a.add(h.multiply(i+1));
sum = sum.add(h.multiply((f(x1).add(f(x2))).divide(2)));
}
return sum;
}
public static void main(String[] args){
Scanner scanner = new Scanner(System.in);
System.out.println("Please enter the lower limit of integration a.");
BigDecimal a = scanner.nextBigDecimal();
System.out.println("Please enter the upper limit of integration b.");
BigDecimal b = scanner.nextBigDecimal();
//swaps a and b so that the bigger of the two is always b.
//this prevents a negative popping up later on.
if(b<a){
BigDecimal r = a;
BigDecimal m = b;
a = m;
b = r;
}
System.out.println("Please enter the number of sampling points N.");
BigDecimal n = scanner.nextBigDecimal();
//checks if n is greater than or equal to 1, and asks for a new value if it isn't.
while (n<1.0){
System.out.println("Please enter a new value for N.");
n = scanner.nextBigDecimal();
}
System.out.println("For " + n + " intervals, the integral of x^2 using the left endpoint rule is: " + leftEndpoint(a,b,n));
System.out.println("Using the midpoint rule, the integral of x^2 is: " + midpoint(a,b,n));
}
}
【问题讨论】:
-
你为什么要尝试使用浮点值作为循环计数器?
-
诀窍是阅读 BigDecimal 的 javadoc。 docs.oracle.com/javase/8/docs/api/java/math/BigDecimal.html
-
这主要是因为我认为。我在我的一个计算中使用它,所以它也必须是 BigDecimal,然后 for 循环中的所有其他内容也必须是 BigDecimal,否则我会得到一个错误的操作数类型错误。
-
BigDecimal 专为用金钱计算而设计。对于物理/数学量,只需使用 double。通过在较大的术语之前将较小的术语相加来避免舍入错误。
-
我不只是加法,我也在乘法和平方,这是我得到舍入错误的时候。我最初的一切都是双倍的,当我切换到 BigDecimal 时,我将如何避免那里的舍入错误?
标签: java bigdecimal