0

I am having trouble editing an existing implementation of Bernoulli numbers in Java which has the BigRational helper class. The original implementation puts the calculation of the Bernoulli numbers inside the Main method. I made a new class to return the calculation for individual Bernoulli numbers. What am I doing wrong?

import java.math.BigInteger;

public class Bernoulli {

    public static void main(String[] args) {
        int N = 20;
        System.out.println(bern(N));

    }

    public static BigRational bern(int N) {
        BigInteger[][] binomial = new BigInteger[N+1][N+1];
        for (int n = 1; n <= N; n++) binomial[0][n] = BigInteger.ZERO;
        for (int n = 0; n <= N; n++) binomial[n][0] = BigInteger.ONE;
        for (int n = 1; n <= N; n++)
            for (int k = 1; k <= N; k++)
                binomial[n][k] = binomial[n-1][k-1].add(binomial[n-1][k]);

        BigRational[] bernoulli = new BigRational[N+1];
        bernoulli[0] = new BigRational(1, 1);
        bernoulli[1] = new BigRational(-1, 2);
        for (int k = 2; k < N; k++) {
            bernoulli[k] = new BigRational(0, 1);
            for (int i = 0; i < k; i++) {
                BigRational coef = new BigRational(binomial[k + 1][k + 1 - i], 
                        BigInteger.ONE);
                bernoulli[k] = bernoulli[k].minus(coef.times(bernoulli[i]));
            }
            bernoulli[k] = bernoulli[k].divides(new BigRational(k+1, 1));
        }
        return bernoulli[N];
    }
}

I am looking to do this in order to calculate the Zeta function for even numbers.

enter image description here

A Test method that I created calculates the denominator of this equation through BigDecimal. I see an upcoming problem, would I need to convert the Bernoulli BigRational into a BigDecimal? I will likely need to adjust the BigRational class I found.

import java.math.BigDecimal;
import java.math.BigInteger;

public class Test {
    public static void main(String[] args) {
        int N = Integer.parseInt("20");

        // precompute binomial coefficients
        BigInteger[][] binomial = new BigInteger[N+1][N+1];
        for (int n = 1; n <= N; n++) binomial[0][n] = BigInteger.ZERO;
        for (int n = 0; n <= N; n++) binomial[n][0] = BigInteger.ONE;

        // bottom-up dynamic programming
        for (int n = 1; n <= N; n++)
            for (int k = 1; k <= N; k++)
                binomial[n][k] = binomial[n-1][k-1].add(binomial[n-1][k]);


        // now compute Bernoulli numbers
        BigRational[] bernoulli = new BigRational[N+1];
        bernoulli[0] = new BigRational(1, 1);
        bernoulli[1] = new BigRational(-1, 2);
        for (int k = 2; k < N; k++) {
            bernoulli[k] = new BigRational(0, 1);
            for (int i = 0; i < k; i++) {
                BigRational coef = new BigRational(binomial[k + 1][k + 1 - i], 
                        BigInteger.ONE);
                bernoulli[k] = bernoulli[k].minus(coef.times(bernoulli[i]));
            }
            bernoulli[k] = bernoulli[k].divides(new BigRational(k+1, 1));
        }
        BigDecimal n = new BigDecimal(6);
        BigDecimal two = new BigDecimal(2);
        System.out.println(fac(n).multiply(two));
        System.out.println("\u03A0^2");


    }

    public static BigDecimal fac(BigDecimal n) {
        if (n.equals(BigDecimal.ZERO)) {
            return BigDecimal.ONE;
        }
        return n.multiply(fac(n.subtract(BigDecimal.ONE)));
    }

}
Axion004
  • 943
  • 1
  • 11
  • 37
  • "What am I doing wrong?" is too broad. Refactor your code, divide it into smaller method (rule of thumb: each method should do one thing and one thing only!). Create a unit-test for each method and see that you're getting the expected output. Once you've done that - you'll narrow down this huge code block to a specific part which is not working and it will be easier to debug and fix. Good luck! – Nir Alfasi Sep 12 '15 at 03:21
  • I found an alternate way of solving the issue. – Axion004 Sep 14 '15 at 03:09

1 Answers1

1

Alternative solution

import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Vector;
import org.apache.commons.math3.fraction.BigFraction;

/* Generates the Bernoulli number, B_n, by a double sum.
     * @param n The index of the Bernoulli number.
     * @return The Bernoulli number at n.
     */
    private static BigFraction bernoulli(int n) {
        BigFraction result = BigFraction.ZERO;
        for (int k = 0; k <= n; k++) {
            BigFraction jSum = BigFraction.ZERO;
            BigInteger bInt = BigInteger.ONE;
            for (int j = 0; j <= k; j++) {
                BigInteger jPowN = (new BigInteger("" + j))
                        .pow(n);
                if (j % 2 == 0) {
                    jSum = jSum.add(bInt.multiply(jPowN));
                } else {
                    jSum = jSum.subtract(bInt.multiply(jPowN));
                }

                /* update binomial(k,j) recursively
                 */
                bInt = bInt.multiply(new BigInteger("" + (k - j))).
                        divide(new BigInteger("" + (j + 1)));
            }
            result = result.add(jSum.divide(new BigInteger("" + (k + 1)))
            );
        }
        return result;
    }
Axion004
  • 943
  • 1
  • 11
  • 37