如何使用BigDecimal增加for循环?

时间:2017-11-08 17:06:05

标签: java bigdecimal

因此,在编码方面,我或多或少都是一个菜鸟。我正在为大学课程学习java,我的一个练习要求我编写一个代码,使用左端点方法,中点方法和梯形方法来评估积分。

为此我需要使用for循环,每次递增一步。我知道如何使用double来做到这一点,但问题是,当我使用double数据类型运行计算时,它会给我舍入错误。在阅读之后(主要是查看其他堆栈溢出问题),我想我应该使用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));
  }
}

3 个答案:

答案 0 :(得分:6)

从0到19计数的正常循环是:

for (int i = 0; i < 20; i++)
    System.out.println(i);

使用BigDecimal完成的相同循环如下所示:

BigDecimal end = BigDecimal.valueOf(20);
for (BigDecimal i = BigDecimal.ZERO; i.compareTo(end) < 0; i = i.add(BigDecimal.ONE))
    System.out.println(i);

<>==等与BigDecimal一起使用的方法是使用compareTo()方法。 javadoc显示了如何执行此操作:

  

对于六个布尔比较运算符(&lt;,==,&gt;,&gt; =,!=,&lt; =)中的每一个,优先提供该方法。执行这些比较的建议习惯是:(x.compareTo(y) &lt; op&gt; 0),其中&lt; op&gt; 是六个比较运算符之一

因此,i < end被写为i.compareTo(end) < 0

另请注意,BigDecimal已为0110BigDecimal.ZEROBigDecimal.ONE和{{3}预定义了常量}},并且创建BigDecimal整数值应该使用BigDecimal.TEN,而不是BigDecimal.valueOf(long val)

答案 1 :(得分:0)

for循环的每一段都可以有你想要的任何表达。第一个初始化变量,第二个必须求值为布尔值,第三个是任何表达式。例如:

for (BigDecimal i = BigDecimal.ZERO; i.compareTo(n) < 0; i = i.add(BigDecimal.ONE)) {
}

答案 2 :(得分:-1)

使用像BigDecimal这样的浮点值作为循环计数器是一个坏主意,因为它可能导致意外行为。你可以在这里阅读更多相关信息: https://www.securecoding.cert.org/confluence/display/java/NUM09-J.+Do+not+use+floating-point+variables+as+loop+counters

如果您创建类型为int的for循环计数器,则可以将其包装在新的BigDecimal实例中以传递给h.multiply()并产生预期结果:

for(int i=0; BigDecimal.of(i).compareTo(n) < 0; i++){
  BigDecimal x1 = a.add(h.multiply(BigDecimal.of(i)));
  BigDecimal x2 = a.add(h.multiply(BigDecimal.of(i+1)));
  sum = sum.add(h.multiply((f(x1).add(f(x2))).divide(2)));
}