Cela vient de http://programmers.blogoverflow.com/2012/08/20-controversial-programming-opinions/
"Étant donné que Pi peut être estimé en utilisant la fonction 4 * (1 - 1/3 + 1/5 - 1/7 +…) avec plus de termes donnant une plus grande précision, écrivez une fonction qui calcule Pi avec une précision de 5 décimales. "
- Remarque, l'estimation doit être effectuée en calculant la séquence donnée ci-dessus.
p=lambda:3.14159
Réponses:
JavaScript,
46 58 5645 octetsMise à jour ES6 : Il s'avère que nous disposons de plus de fonctionnalités maintenant que cinq ans se sont écoulés.
Cette version ( 45 octets; oui,
let
c'est obligatoire) fonctionne en mode strict ES6 en théorie . En pratique, vous pouvez l'exécuter en V8 (par exemple avec un nœud) avec--use-strict --harmony-tailcalls
; la fonction Propre Tailcalls n'est pas encore largement implémentée, hélas. Cependant, c'est un comportement spécifié, donc ça devrait aller.Si nous voulons nous en tenir à ce qui est largement implémenté et ne pas nécessiter de mode strict, nous pouvons simplement utiliser la syntaxe de la flèche fatale ES6 pour les fonctions, mais sinon conserver la même implémentation qu'auparavant (suggérée par Brian H) pour un coût de 48 octets.
Le choix du nom pour le paramètre unique n'a pas vraiment d' importance, mais nous pourrions aussi bien choisir l'un des noms que nous utilisons afin de minimiser la pollution de portée mondiale.
Cette version est une expression de fonction; ajoutez deux caractères (par exemple "
f
") si vous voulez qu'il soit nommé. Cette version saisit les mondiauxa
eti
; cela pourrait être évité si nous ajoutions "a,i
" à la liste des paramètres.Utilise une version reformulée de l'algorithme afin de contourner le besoin de soustraction.
Voici une version "simple" sans cet ajustement:
qui horloge à
6462 caractères.Merci à @ardnew pour la suggestion de se débarrasser de l'
4*
avant avant lereturn
.Histoire
la source
a+=2/i/-~-~i;return 4*a
ena+=8/i/-~-~i;return a
Python 59 octets
Cela imprime 1000 chiffres; légèrement plus que le nombre requis 5. Au lieu d'utiliser l'itération prescrite, il utilise ceci:
Le
6637
(dénominateur le plus intérieur) peut être formulé comme:Cela implique une convergence linéaire. Chaque itération plus profonde produira un bit binaire supplémentaire de pi .
Si , cependant, vous insistez pour utiliser l'identité tan -1 , une convergence similaire peut être obtenue, si cela ne vous dérange pas de traiter le problème légèrement différemment. Jetons un œil aux sommes partielles:
4.0, 2.66667, 3.46667, 2.89524, 3.33968, 2.97605, 3.28374, ...
il est évident que chaque terme saute d'avant en arrière de chaque côté du point de convergence; la série a une convergence alternée. De plus, chaque terme est plus proche du point de convergence que le terme précédent. il est absolument monotone par rapport à son point de convergence. La combinaison de ces deux propriétés implique que la moyenne arithmétique de deux termes voisins est plus proche du point de convergence que l'un ou l'autre des termes eux-mêmes. Pour vous donner une meilleure idée de ce que je veux dire, considérez l'image suivante:
La série externe est l'original, et la série interne est trouvée en prenant la moyenne de chacun des termes voisins. Une différence remarquable. Mais ce qui est vraiment remarquable, c'est que cette nouvelle série a également une convergence alternée, et est absolument monotone par rapport à son point de convergence. Cela signifie que ce processus peut être appliqué à maintes reprises, ad nauseum.
D'accord. Mais comment?
Quelques définitions formelles. Soit P 1 (n) le n ème terme de la première séquence, P 2 (n) le n ème terme de la deuxième séquence, et de même P k (n) le n ème terme de la k ème séquence tel que défini ci-dessus .
P 1 = [P 1 (1), P 1 (2), P 1 (3), P 1 (4), P 1 (5), ...]
P 2 = [(P 1 (1) + P 1 (2)) / 2, (P 1 (2) + P 1 (3)) / 2, (P 1 (3) + P 1 (4)) / 2, (P 1 (4) + P 1 (5)) / 2, ...]
P 3 = [(P 1 (1) + 2P 1 (2) + P 1 (3)) / 4, (P 1 (2) + 2P 1 (3) + P 1 (4)) / 4, (P 1 (3) + 2P 1 (4) + P 1 (5)) / 4, ...]
P 4 = [(P 1 (1) + 3P 1 (2) + 3P 1 (3) + P 1 (4)) / 8, (P 1 (2) + 3P 1 (3) + 3P 1 (4) + P 1 (5)) / 8, ...]
Sans surprise, ces coefficients suivent exactement les coefficients binomiaux et peuvent être exprimés comme une seule ligne du triangle de Pascal. Puisqu'une ligne arbitraire du triangle de Pascal est triviale à calculer, une série arbitrairement «profonde» peut être trouvée, simplement en prenant les n premières sommes partielles, multipliez chacune par le terme correspondant dans la k ème ligne du triangle de Pascal et en divisant par 2 k-1 .
De cette façon, une précision complète en virgule flottante 32 bits (~ 14 décimales) peut être obtenue avec seulement 36 itérations, point auquel les sommes partielles n'ont même pas convergé sur la deuxième décimale. Ce n'est évidemment pas joué au golf:
Si vous vouliez une précision arbitraire, cela peut être obtenu avec une petite modification. Ici encore, calcul de 1000 chiffres:
La valeur initiale de p commence 2 10 plus grande, pour contrer les effets de division entière de s / d lorsque d devient plus grand, ce qui fait que les derniers chiffres ne convergent pas. Remarquez ici encore que
3318
c'est aussi:Le même nombre d'itérations que le premier algorithme (réduit de moitié car t diminue de 1 au lieu de 2 à chaque itération). Encore une fois, cela indique une convergence linéaire: un bit binaire de pi par itération. Dans les deux cas, 3318 itérations sont nécessaires pour calculer 1000 chiffres de pi , soit un quota légèrement meilleur que 1 million d'itérations pour en calculer 5.
la source
4 * sum(1/(1+i*2) if not i%2 else -1/(1+i*2) for i in xrange(places*10**(places)))
k → ∞
,f(-1,k)
s'approche de votre somme d'Euler.P_1 = ..., P_2 = ..., P_3 = ..., P_4 = ...
", ... multipliez chacun par le terme correspondant dans lakth
ligne du triangle de Pascal et en divisant par2^{k-1}
", au lieu de lanth
ligne et2^{n-1}
?.Mathematica
42 39 34 33 31 2632Approche d'Archimède 26 caractères
Cela atteint le critère lorsque l'entrée est 822.
Question: Quelqu'un sait-il comment il a calculé le péché de 180 degrés? Je ne.
Approche de Leibniz (série de Gregory) 32 caractères
C'est la même fonction que le poseur de problèmes a donné comme exemple. Il atteint le critère en environ un demi-million d'itérations.
Approche Madhava-Leibniz 37 caractères
Cette variation utilise quelques caractères supplémentaires mais converge vers le critère en seulement 9 itérations!
la source
APL (14)
la source
--/4÷1-2×⍳1e6
Java (67 caractères)
Notez que cela évite la perte de signification en additionnant les nombres dans le bon ordre.
la source
while(--i>0)
pourwhile(i--)
et enregistrer 2 caractèresHaskell, 32
Compter un nom de fonction c'est
34
la source
R - 25 caractères
la source
C (GCC) (44 caractères)
Cela fait 41 caractères, mais il doit également être compilé avec
-O2
pour que l'optimiseur élimine la récursivité de la queue. Cela repose également sur un comportement indéfini par rapport à l'ordre dans lequel les++
sont exécutés; merci à ugoren de l'avoir signalé. J'ai testé avec gcc 4.4.3 sous Linux 64 bits.Notez qu'à moins que l'optimiseur ne réordonne également la somme, il ajoutera à partir du plus petit nombre, donc il évite la perte de signification.
Appelez le
p()
.la source
q()
pasp()
. Et je ne pense pas que cela-O2
devrait être compté (mais si vous le comptez, c'est 4 caractères en raison de l'espace requis).p(0)
. 3. Enregistrez un caractère parreturn++i...
. 4. Deux++i
rend le comportement indéfini.q
- cela m'apprendra à revérifier après avoir renommé. Je pense que je suis la pratique normale de compter-O2
comme 3 caractères, mais nous pouvons l'ouvrir sur méta si vous voulez; meta.codegolf.stackexchange.com/questions/19 est la seule discussion pertinente que je puisse trouver. J'ai ajouté la version de gcc que j'utilise et qui me permet de l'appeler commep()
. L'enregistrement du caractère arrête l'optimiseur et donne une erreur de segmentation. Je préciserai que j'utilise un comportement non défini, selon meta.codegolf.stackexchange.com/questions/21p()
- êtes-vous sûr que l'appel àp()
partir de n'importe quel contexte fonctionnerait? Ou est-ce juste ce qui se trouvait sur la pile lors de votre test?p()
vsp(0)
, mais je ne sais pas quel comportement il documente et je ne suis pas vraiment un programmeur C.J, 26 caractères
+ / + / _ 2 ((4 _4) &%)>: +: i.100Passé de 100 éléments de séquence à 1e6 éléments. De plus, il s'agit maintenant d'un code balisé et peut être copypassé du navigateur vers la console sans erreur.
la source
-/4%>:2*i.1e6
- 13 caractères. (Merci à b_jonas dans #jsoftware de m'avoir fait réaliser que cela-/
fonctionne pour calculer une somme avec un signe alterné. [C'est parce que tous les opérateurs de J sont de priorité égale et associatifs à droite, donc-/ 1 2 3 4
<=>1 - (2 - (3 - 4))
<=>1 - 2 + 3 - 4
.])Javascript - 33 caractères
Appelez en
p
passant un nombre impair positifx
et il calculera Pi avec des(x-1)/2
termes.la source
Rubis - 82 caractères
Essayez-le: https://repl.it/LQ8w
L'approche utilise indirectement la série donnée en utilisant une approche d'accélération numérique. La sortie résultante est
pi ≈ 3.14159265161
contre.
pi = 3.14159265359
Ça commence par
Et puis, puisque c'est alternatif, nous pouvons accélérer la convergence en utilisant
Et cela s'applique à plusieurs reprises:
Et pour plus de simplicité,
f(n) = f(n,n)
.Rubis - 50 caractères
Si cela ne vous dérange pas de courir très longtemps, vous pouvez simplement utiliser
ou
la source
C, 69 caractères
a
est initialisé à 1).void main
est étrange et non standard, mais fait fonctionner les choses. Sans cela, la récursivité est implémentée comme un véritable appel, conduisant à un débordement de pile. Une alternative est d'ajouterreturn
.4*
peuvent être enregistrés s'ils s'exécutent avec trois paramètres de ligne de commande.la source
int main(a)
ou mêmemain(a)
, GCC ne donne qu'un avertissement. Et cela donnera un avertissement devoid main
toute façon, et peut-être même parce que vous n'avez qu'un seul argumentmain
.Clojure - 79 caractères
Cela crée une fonction sans arguments qui calculera un flottant qui se rapproche de pi correctement à cinq décimales. Notez que cela ne lie pas la fonction à un nom tel que
pi
, donc ce code doit être évalué en place aveceval
as(<code>)
ou lié à un nom auquel cas la solution estpour 82 caractères
Sur
la source
PHP -
5655 caractèresJe ne sais pas si je peux l'obtenir beaucoup plus petit sans enfreindre la règle de l'algorithme.
la source
<?for(;1e6>$j;)$p+=($i=-$i|4)/~-$j+=2;echo$p;
Perl -
4339 caractèrespas sûr des règles sur les sous-programmes anonymes, mais voici une autre implémentation utilisant la construction en série de @ FireFly
la source
Java -
9284 caractèresJe ne peux pas battre de loin le résultat de Peter Taylor, mais voici le mien:
Version non golfée:
Modifier: enregistré quelques caractères à l'aide de l'opérateur ternaire.
la source
Python - 56 caractères
Meh, Mon python-fu n'est pas assez fort. Je ne pouvais pas voir plus de raccourcis, mais peut-être qu'un golfeur plus expérimenté pourrait trouver quelque chose à couper ici?
la source
4.
->4
). Dans d'autres nouvelles, je viens de trouver un cas où Python 3 bat réellement Python 2 dans le golf de code!Rubis - 54 caractères
Mon premier essai sur console
63 caractères.
la source
def a;
au lieu dedef a()
.Perl (76 caractères)
(Résultat: 3.14159052)
Pas la solution la plus courte possible, mais peut-être intéressante. C'est géométrique. Je calcule l'aire sous un cercle.
J'ai une autre approche amusante, mais c'est vraiment lent. Il compte le nombre de points discrets dans un carré qui sont en dessous d'un quart de cercle et calcule pi à partir de celui-ci:
Il attend le nombre d'itérations comme argument de ligne de commande. Ici, vous pouvez voir comment le temps d'exécution est lié à la précision. ;)
la source
k (25 caractères)
4 * + /% (i # 1 -1) '1 + 2 ! I: 1000000Légèrement plus court:
la source
Python (49)
la source
CJam - 21
Calcul assez simple de la série donnée.
CJam est http://sf.net/p/cjam
la source
Julia - 30 personnages
la source
SQL, 253 octets
Je fournirais un SQL Fiddle, mais cela va trop de boucles pour trouver les fractions 1/3 1/5 1/7 etc. et donne des erreurs lol. Cependant, si vous passez
@B<100000
à1000
alors il s'exécute (évidemment pas au même nombre de chiffres de précision).la source
Befunge, 129 octets
Essayez-le en ligne!
Au cas où quelqu'un se demanderait, c'est un éléphant.
la source