package javacodebook.core.bignumber; import java.math.*; /** * Mit Hilfe dieser Klasse lassen sich die mathematischen * Konstanten Pi und e mit sowie einige trig. Funktionen * mit beliebiger Genauigkeit berechnen. */ public class CalcExample { static final BigDecimal ZERO = new BigDecimal(0); static final BigDecimal ONE = new BigDecimal(1); static final BigDecimal FOUR = new BigDecimal(4); static final int ROUND_ME = BigDecimal.ROUND_HALF_EVEN; /** * Berechnet den Wert von e nach der Summen-Formel * e = 1/0! + 1/1! + 1/2! + 1/3! + ... */ public static BigDecimal euler(int scale) { BigDecimal factor = new BigDecimal(1); BigDecimal factmul = new BigDecimal(1); BigDecimal result = new BigDecimal(0); while (true) { // Berechne die Zahl 1 / akt. Faktor. Es wird // eine Nachkommastellen mehr gespeichert um // evtl. Rundungsfehler zu vermeiden. BigDecimal x = ONE.divide(factor, scale+ 1, ROUND_ME); // Wenn der Faktor Null ist, dann abbrechen if (x.compareTo(ZERO) == 0) break; // Das aktuelle Ergebniss wird zum // Gesamtergebnis addiert result = result.add(x); // Den neuen Summanden berechnen. Der Summand // ergibt sich aus 1/x! = 1/(x-1)! * 1/x factor = factor.multiply(factmul); factmul = factmul.add(ONE); } return result.setScale(scale, ROUND_ME); } /** * Berechnet den Wert von pi nach der Machin-Formel: * pi/4 = 4*arctan(1/5) - arctan(1/239) */ public static BigDecimal pi(int scale) { BigDecimal arctan_1_5 = arctan(0.2, scale+5); BigDecimal arctan_1_239 = arctan(1d/239d, scale+5); BigDecimal pi = arctan_1_5.multiply(FOUR).subtract( arctan_1_239).multiply(FOUR); return pi.setScale(scale, ROUND_ME); } /** * Berechnung den arctan(x) nach der folgenden Formel: * arctan(x) = x - (x^3)/3 + (x^5)/5 - (x^7)/7 + ... */ public static BigDecimal arctan(double x, int scale) { if (x>=1 || x<=-1) return null; BigDecimal result = new BigDecimal(x); BigDecimal numer = new BigDecimal(x); BigDecimal denom = new BigDecimal(0); BigDecimal help = new BigDecimal(x*x); BigDecimal term = new BigDecimal(1); int i = 1; while (true) { numer = numer.multiply(help); denom = new BigDecimal(2*i+1); term = numer.divide(denom, scale, ROUND_ME); if (term.compareTo(ZERO) == 0) break; if (i%2 != 0) result = result.subtract(term); else result = result.add(term); i++; } return result; } /** * Berechnung des Sinus mit der foldenen Formel: * sin(x) = x - (x^3)/3! + (x^5)/5! - (x^7)/7! + ... */ public static BigDecimal sin(double x, int scale) { BigDecimal result = new BigDecimal(0); BigDecimal numer = new BigDecimal(x); BigDecimal denom = new BigDecimal(1); BigDecimal help = new BigDecimal(x*x); BigDecimal term = new BigDecimal(1); int i=1; while (true) { term = numer.divide(denom, scale+1, ROUND_ME); if (term.compareTo(ZERO) == 0) break; if (i%2 == 1) result = result.add(term); else result = result.subtract(term); numer = numer.multiply(help); denom = denom.multiply( new BigDecimal(2*i*(2*i+1))); i++; } return result.setScale(scale, ROUND_ME); } /** * Berechnung des Cosinus mit der foldenen Formel: * cos(x) = 1 - (x^2)/2! + (x^4)/4! - (x^6)/6! + ... */ public static BigDecimal cos(double x, int scale) { BigDecimal result = new BigDecimal(0); BigDecimal numer = new BigDecimal(1); BigDecimal denom = new BigDecimal(1); BigDecimal help = new BigDecimal(x*x); BigDecimal term = new BigDecimal(1); int i=1; while (true) { term = numer.divide(denom, scale+1, ROUND_ME); if (term.compareTo(ZERO) == 0) break; if (i%2 == 1) result = result.add(term); else result = result.subtract(term); numer = numer.multiply(help); denom = denom.multiply( new BigDecimal((2*i)*(2*i-1))); i++; } return result.setScale(scale, ROUND_ME); } }