Taux circonférentiel à Java

introduction

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.

programme

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);
	}
}

Exemple d'exécution

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

À propos du temps requis

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.

Autre

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;
	}

référence

Recommended Posts

Taux circonférentiel à Java
Changements dans Java 11
Janken à Java
FizzBuzz en Java
Lire JSON en Java
Faites un blackjack avec Java
Programmation par contraintes en Java
Mettez java8 dans centos7
NVL-ish guy en Java
Joindre des tableaux en Java
"Hello World" en Java
Interface appelable en Java
Commentaires dans la source Java
Fonctions Azure en Java
Formater XML en Java
Simple htmlspecialchars en Java
Hello World en Java
Utiliser OpenCV avec Java
Mémorandum WebApi avec Java
Détermination de type en Java
Exécuter des commandes en Java (ping)
Divers threads en java
Implémentation du tri de tas (en java)
API Zabbix en Java
POST JSON en Java
Manipulation de la date dans Java 8
Nouveautés de Java 8
Utiliser PreparedStatement en Java
Nouveautés de Java 9,10,11
Exécution parallèle en Java
Essayez d'utiliser RocksDB avec Java
Évitez l'erreur que Yuma a donnée en Java
Obtenir des informations EXIF en Java
Modifier ini en Java: ini4j
L'histoire de Java dans ce monde
Essayez d'appeler JavaScript en Java
Essayez le type fonctionnel en Java! ①
J'ai fait une roulette à Java.
Implémentation de l'authentification en deux étapes en Java
Refactoring: faire du Blackjack en Java
Analyse de sujets (LDA) en Java
Prétraitement NEologd en Java neologdn-java
Changer le codage Java dans Windows
API Java Stream en 5 minutes
Problème de ne pas trouver javax.annotation.Généré en Java 11
Lire l'entrée standard en Java
Implémenter l'authentification de base en Java
Rechercher un sous-ensemble en Java
[Java] Obtenir KClass en Java [Kotlin]
Créer des fonctions Azure en Java
Importer des données Excel avec Java
Implémenter une combinaison de mathématiques en Java
Construction de l'environnement JavaFX dans Java 13
Java
Modèle de stratégie Enum en Java
2 Implémentez une analyse syntaxique simple en Java