Pi

 

page sur Pi...


David Cobac 22/06/2004 : Je commence (comme ça je peux dire des trucs simples :) ).

Voici une illustration de la méthode de MonteCarlo pour déterminer des valeurs approchées.

 # auteur : David Cobac

 set N 0
 set FreqDans 0

 # Procédure : Coords
 # Arguments : nb --> nombre de coordonnées à renvoyer
 # Renvoi    : renvoi d'une liste de nb coordonées aléatoires
 #             comprises entre 0 et 1

 proc Coords {nb} {

    for {set i 1} {$i<=$nb} {incr i} {
	lappend maListe [expr {rand()}] [expr {rand()}]
    }

    return $maListe
 }

 # Procédure : Controle
 # Arguments : x --> abscisse du point
 #             y --> ordonnée du point
 # Action    : Met à jour le nombre de lancers effectués et la
 #             fréquence du nombre de points dans le cercle

 proc Controle {x y} {
    global N FreqDans

    incr N
    set test [expr {$x*$x+$y*$y<=1}]

    set FreqDans [expr {($FreqDans*($N-1)+$test)/double($N)}]
    .l configure -text [expr {$FreqDans*4}]
    update
 }

 # Procédure : Lancers
 # Arguments : nb --> nombre de lancers
 # Action    : Dessine les points sur le canevas, met à jour
 #             l'affichage du nombre de lancers

 proc Lancers {nb} {
    global N

    set H [.c cget -height]

    foreach {absc ordo} [Coords $nb] {
	Controle $absc $ordo
	set x [expr {$absc*$H}]
	set y [expr {$H-$ordo*$H}]
	.c create rectangle $x $y $x $y -tags point
    }

    .c delete texte
    .c create text [expr {$H/2}] [expr {$H/2}] \
	-text $N\ lancers -tags texte -font {Courier 21 bold} -fill black
 }

 # Procédure : RAZ
 # Arguments :
 # Action    : (R)éinitialise les variables globales, efface les points
 #             de l'écran, bref remet tout à zéro ...

 proc RAZ {} {
    global N FreqDans
    set N 0
    set FreqDans 0

    .c delete texte
    .c delete point
    .l configure -text 0
 }

 # Procédure : gui
 # Arguments : HautEcran --> Hauteur de l'écran
 # Action    : Procédure principale, définissant les actions
 #             à effectuer suivant l'interface graphique.

 proc gui {HautEcran} {
    global FreqDans

    wm title . "Illustration Méthode de Monte-carlo"
    wm resizable . false false

    set HautC [expr {$HautEcran*.75}]
    canvas .c -width $HautC -height $HautC -bg white
    button .b0 -text "1 lancer"      -command "Lancers 1"
    button .b1 -text "100 lancers"   -command "Lancers 100"
    button .b2 -text "1000 lancers"  -command "Lancers 1000"
    button .b3 -text "Remise  Zro" -command "RAZ"
    label .l -width 10 -text 0

    bind .l <Enter> ".l configure -text [expr {4*atan(1)}]"
    bind .l <Leave> ".l configure -text \[expr 4*\$FreqDans\]"

    pack .c -expand 1
    pack .l -expand 1 -fill x
    pack .b0 -side left -expand 1 -fill x
    pack .b1 -side left -expand 1 -fill x
    pack .b2 -side left -expand 1 -fill x
    pack .b3 -side left -expand 1 -fill x

    .c create oval [expr -$HautC] 0 $HautC [expr 2*$HautC] \
	-outline red -fill "#fff0f0"
 }

 gui [winfo screenheight .]

RS: Si on veut le valeur de Pi dans une calculation, la méthode plus simple est

 expr acos(-1)

Kroc : Pour obtenir une valeur assez précise de Pi on peut utiliser la formule de Machin :

 set tcl_precision 17
 set pi [expr 16 * atan(1./5) - 4 * atan(1./239)]
 3.1415926535897936

VWa: Normalement à ce stade il y a TOUJOURS quelqu'un qui écrit :

  set pi 3.14159265358979323846264338327950288

ce qui n'apporte rien au débat

et d'ailleurs j'observe que ta dernière décimale est fausse, Kroc ;-)


KBK Voici pi, jusqu'à 2.400 chiffres, dans Tcl obfusqué:

 proc pi {} {
     set n 2400
     set e 0
     set f {}
     for { set b 0 } { $b <= 8400 } { incr b } {
 	lappend f 2000
     }
     for { set c 8400 } { $c > 0 } { incr c -14 } {
 	set d 0
 	set g [expr { $c * 2 }]
 	set b $c
 	while 1 {
 	    incr d [expr { [lindex $f $b] * 10000 }]
 	    lset f $b [expr {$d % [incr g -1]}]
 	    set d [expr { $d / $g }]
 	    incr g -1
 	    if { [incr b -1] == 0 } break
 	    set d [expr { $d * $b }]
 	}
 	puts -nonewline [format %04d [expr { $e + $d / 10000 }]]
 	flush stdout
 	set e [expr { $d % 10000 }]
     }
     puts {}
 }
 pi

AM Parce que des valeurs comme pi sont si communes, j'ai cree un petit module dans le librairie Tcllib qui donne des precises valeurs pour pi, e, la constante d'Euler, et quelques autres. On utilise simplement un commande comme [constants pi e ...] pour importer ces constantes dans le "namespace" courant.

L'avantage: on n'a plus besoin de memoriser des formules ou des valeurs assez precises.

Neanmoins, des petits concours comme celui-ci pour produire des programmes qui rendent pi ou zeta(3) dans seulement quelques lignes de code resteront bien amusants!


David Cobac : Encore un petit truc qui tend vers Pi (pour peu qu'on puisse travailler sur l'ensemble de tous les entiers positifs (dits naturels) :

 proc pgdc {a b} {
     while {$b!=0} {
        set a_ $b
        set q [expr {$a/$b}]
        set b [expr {$a-$b*$q}]
        set a $a_
     }
     return $a
 }

 set occurences 0
 set nbExp 10000

 for {set i 1} {$i<=$nbExp} {incr i} {
     set ent1 [expr {int(rand()*1000000+1)}]
     set ent2 [expr {int(rand()*1000000+1)}]
     if {[eval pgdc [lsort -decreasing -integer "$ent1 $ent2"]] == 1} {
        incr occurences
     }
 }

 puts "$occurences sur $nbExp expériences"
 puts "Valeur Approchée de Pi déduite : [expr {sqrt(6.*$nbExp/$occurences)}]"

C'est basé sur le fait que la probabilité pour que deux entiers soient premiers entre eux est 6/Pi².

Kroc - 28 Juin 2004 - J'ai déplacé ce qui suivait dans Défis mathématiques.


Catégorie Mathématiques