Dans cet article, nous utiliserons la formule suivante pour calculer le rapport de circonférence en Java.
\frac{4}{\pi}=\sum_{n=0}^\infty \frac{(-1)^n(4n)!(1123+21460n)}{882^{2n+1}(4^nn!)^4}
C'est l'officiel de Ramanujan (1887/12/22 --1920 / 4/26). En le regardant sévèrement, je me demande comment j'ai trouvé cela et comment cela me donne vraiment un rapport de circonférence.
(Je ne sais pas de quelle formule il s'agit) Les échanges suivants sont également mystérieux.
Professeur Hardy "Veuillez me dire comment vous avez trouvé cette formule." Ramanujan "S'il vous plaît, croyez-moi, la déesse Namagiri s'est tenue au chevet du lit et m'a appris."
Je veux vraiment le calculer.
En gros, c'est un programme sans aucune ingéniosité.
--La molécule et le dénominateur sont calculés respectivement par BigInteger. --Big Decimal est utilisé pour diviser la fraction (dans ce programme, la précision est spécifiée pour la première fois). ―― Comme il est trop terrible d'effectuer le même calcul encore et encore, nous «développons» pour réutiliser le résultat du calcul précédent. --Le dernier chiffre contient l'erreur (l'erreur est proportionnelle au "nombre de répétitions").
PamaPi.java
/**
*Calculez le rapport de circonférence.
*/
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
public class RamaPi {
/**
*Calculez le sol(Réutiliser le résultat du calcul précédent)。
*/
class Facto {
/**Dernier argument*/
int n = 1;
/**Dernière valeur*/
BigInteger val = BigInteger.ONE;
BigInteger calc(final int arg) {
for ( ; n <= arg ; n++) {
val = val.multiply(BigInteger.valueOf(n));
}
return val;
}
}
/**Pour le calcul de multiplication 1*/
Facto workFacto1 = new Facto();
/**Pour le calcul du sol 2*/
Facto workFacto2 = new Facto();
/**Constante "882"*/
static final BigInteger VAL_882 = BigInteger.valueOf(882);
/**Constante «4»*/
static final BigInteger VAL_4 = BigInteger.valueOf(4);
/**
*Calculez la molécule officielle de Ramanujan.
*/
BigInteger bunsi(final int n) {
final int sign = (n&1) == 0 ? 1 : -1;
final BigInteger a = workFacto1.calc(4 * n);
final BigInteger b = BigInteger.valueOf(sign * (1123 + 21460*n));
return a.multiply(b);
}
/**
*Calculez le dénominateur officiel de Ramanujan.
*/
BigInteger bunbo(final int n) {
final BigInteger a = VAL_882.pow(2*n+1);
final BigInteger b = VAL_4.pow(n);
final BigInteger c = workFacto2.calc(n);
final BigInteger d = b.multiply(c).pow(4);
return a.multiply(d);
}
/**
*Calculez le rapport de circonférence à partir de la formule de Ramanujan.
*/
void calc(final int digits) {
BigDecimal sum = BigDecimal.ZERO;
/**Nombre de chiffres pour arrêter l'ajout (moins de ce nombre de chiffres ne peut pas être ajouté)*/
final BigDecimal thr = BigDecimal.ONE.divide(BigDecimal.TEN.pow(digits));
/**Il est temps de commencer le calcul*/
long t0 = System.nanoTime();
int iter = 0;
for ( ;; iter++ ) {
final BigDecimal bunbo = new BigDecimal(bunbo(iter));
final BigDecimal bunsi = new BigDecimal(bunsi(iter));
final BigDecimal adder = bunsi.divide(bunbo, digits, RoundingMode.HALF_EVEN);
if (adder.abs().compareTo(thr) < 0) {
break;
}
/*Réécrire la somme avec le résultat de l'addition*/
sum = sum.add(adder);
/*Si le nombre de chiffres est petit, l'état de convergence est affiché.*/
if (digits < 100) {
System.out.println( BigDecimal.valueOf(4).divide(sum, digits, RoundingMode.HALF_EVEN));
}
}
/**Heure à laquelle le calcul a été terminé*/
long t1 = System.nanoTime();
System.err.println("Nombre de répétitions: " + iter);
double elapsed = (t1 - t0) / ((double)1000 * 1000 * 1000);
System.err.println("Nombre de secondes requis: " + String.format("%.6f", elapsed));
System.out.println(BigDecimal.valueOf(4).divide(sum, digits, RoundingMode.HALF_EVEN));
}
static public void main(String arg[]) {
int digits = Integer.parseInt(arg[0]);
new RamaPi().calc(digits);
}
}
Spécifiez le nombre de chiffres dans l'argument. Il peut y avoir une erreur dans les derniers chiffres (l'erreur est proportionnelle au "nombre de répétitions").
java RamaPi 50
3.14158504007123775601068566340160284951024042742654
3.14159265359762201426827517920229156338712376594028
3.14159265358979322988767708881201158250039662639857
3.14159265358979323846265313702144396820307036308333
3.14159265358979323846264338326814215966511742779251
3.14159265358979323846264338327950289764449222972749
3.14159265358979323846264338327950288419715329619277
3.14159265358979323846264338327950288419716939939455
3.14159265358979323846264338327950288419716939937511
Nombre de répétitions: 9
Nombre de secondes requis: 0.003002
3.14159265358979323846264338327950288419716939937511
J'ai mesuré un peu dans l'environnement à portée de main. Cela prend beaucoup de temps, mais pensez-vous que le calcul de plusieurs longueurs de Java est rapide ou lent?
Nombre de chiffres | Nombre de répétitions | Nombre de secondes requis | Μs par temps |
---|---|---|---|
10 | 2 | 0.001129 | 564.5 |
100 | 18 | 0.003077 | 170.9 |
1000 | 170 | 0.049033 | 288.4 |
10000 | 1698 | 4.237159 | 2495.3 |
20000 | 3395 | 19.83075 | 5841.1 |
40000 | 6790 | 118.651706 | 17474.4 |
Quand j'ai essayé de déplacer «Superπ» dans le même environnement, «8,38 millions de chiffres» était «152 secondes» (200 fois le nombre de chiffres, ce qui est différent).
Si vous voulez gagner en vitesse, utilisez quelque chose pour des opérations de précision multiples comme GMP (La bibliothèque arithmétique de précision multiple GNU) au lieu de BigInteger / BigDecimal de Java. C'est définitivement mieux.
Au départ, il s'agissait d'une implémentation naïve de revêtement de sol, mais cela n'a pris que 20 000 chiffres et 113 secondes. (Au début, je l'ai écrit de manière récursive, mais il a immédiatement débordé: silencieux :)
.java
/**
*Calculez le plancher.
*/
static final BigInteger facto(final int a) {
BigInteger work = BigInteger.ONE;
for (int i=2 ; i<=a ; i++) {
work = work.multiply(BigInteger.valueOf(i));
}
return work;
}
[Shrinivasa Ramanujan (Wikipedia)](https://ja.wikipedia.org/wiki/%E3%82%B7%E3%83%A5%E3%83%AA%E3%83%8B%E3 % 83% B4% E3% 82% A1% E3% 83% BC% E3% 82% B5% E3% 83% BB% E3% 83% A9% E3% 83% 9E% E3% 83% 8C% E3% 82 % B8% E3% 83% A3% E3% 83% B3)
[Calcul de précision arbitraire](https://ja.wikipedia.org/wiki/%E4%BB%BB%E6%84%8F%E7%B2%BE%E5%BA%A6%E6%BC%94% Article d'introduction sur E7% AE% 97) (Wikipedia)
Si vous souhaitez effectuer un calcul de longueur multiple plus approprié, GMP
[Programme de calcul du rapport de circonférence proéminent](http: // circumference ratio.jp/program/introduction.html)
Recommended Posts