Forum de mathématiques - Bibm@th.net
Vous n'êtes pas identifié(e).
- Contributions : Récentes | Sans réponse
- Accueil
- » Programmation
- » Programme python en Haskell
- » Répondre
Répondre
Résumé de la discussion (messages les plus récents en premier)
- LEG
- 10-11-2022 06:21:09
Ok , pas de souci. merci
- rareStrophe
- 09-11-2022 16:57:46
Pourquoi ? Je t'ai dis que tu sembles pouvoir installer le paquet ghc.
- LEG
- 09-11-2022 14:20:08
Oui c'est ce que m'a confirmé le collègue qui s'occupe de mon PC , lorsque j'ai un souci pour charger une application ... donc je verrai par la suite pour le télécharger sur le site Hasquell ...
HASKELL
- rareStrophe
- 09-11-2022 12:38:23
Cela fait un moment que je n'ai pas utilisé Ubuntu, et visiblement tout a été changé de place. Il semblerait qu'il faille maintenant installer le paquet ghc. Je mets à jour.
- LEG
- 09-11-2022 07:00:58
Bonjour:
Re;
Pour installer Haskell, deux options s'offrent à vous, le télécharger depuis le site du projet ou l'installer depuis le gestionnaire de paquet de votre système d'exploitation préféré :
# Pour Ubuntu
$ apt-get install haskell-platform
J'ai vérifié sur mon système ; je suis allé dans gestionnaire de paquets synaptiques ; ce paquet ne figure pas , il y a uniquement : @ apt
Donc je suppose qu'il me faudra aller sur la plateforme Haskell pour télécharger cette application ...?
- LEG
- 07-11-2022 13:47:49
Re : rassure toi je ne m'impatiente pas du tout , le but est que tu prennes ton temps , et qu'effectivement il soit plus rapide que python .
Pour info en C++ , ce programme complet met pour le résultat avec n = 999 999 999 les deux dernières parties ; 0,0879 secondes et 0,08873 seconde , cela te permettra de voir une fois le tout complété ... Merci pour ton aide et tes explications...
Il est clair que l'édition des nombres premiers , ou les tableaux criblé, prennent du temps , mais ce n'est pas le but , éditer les [tableau / liste] de 1 , criblé c'est bon jusqu'à $n = 300 000$ maxi , car ensuite c'est comme regarder des grains de sables sur la plage ...
Bonne après midi .
- rareStrophe
- 07-11-2022 13:34:56
Juste avant de partir en cours, j'ai refait le benchmark avec arithmoi… résultat : 18 ms en moyenne pour générer la liste des premiers qui nous intéressent ! 15 fois plus rapide que la version naïve et 2 fois plus rapide que la version Python et sans autre tips and tricks.
Sur ce, je vais en cours !
- rareStrophe
- 07-11-2022 12:33:04
Comme je l'ai écris au début du premier post commençant les explications, si tu as des questions, demande ! Même si tu devras attendre ce soir car je retourne en cours ! ^^
Enfin, car je vois que tu t'impatientes déjà, ne t'inquiète pas. Lorsque j'aurais complété le tout, je posterai le code source avec les explications de comment compiler et lancer le tout. Peut-être même les versions compilées ? En jouant avec GitHub CI ça doit être possible de le faire pour toutes les plateformes.
- LEG
- 07-11-2022 12:27:53
Ok , j'ai lu ... mais je ne comprend pas tout ..., effectivement je comprend le but de tes explications, mais pour quelqu'un qui fait ou veut modifier le programme .
En python j'ai su le faire (sur certaine partie) mais surement pas en C++ ...
Je pense que Yoshi serra à même de voire la différence ...
Moi je ne peux que tester , comme tu l'as très bien fait d'ailleurs ...
Je vais me comporter comme la tortue et non comme le renard...
- rareStrophe
- 07-11-2022 11:39:00
Ceci dit : gagner du temps sur cette première partie du programme de la def eratostene(n): qui énumère les nombres premiers $P\leq \sqrt{(n)}$
permettra de gagner du temps, dans la deuxième et troisième partie ...
Je sais...
Mais pourquoi avoir extrait tous les nombres premiers < 3000 , pour comparer les vitesses (éfficacité) des deux langages de programmation je suppose suite à tes explications....
Ce n'est pas ce que j'ai fais.
N'oublies pas que pour $n=999999999$ , c'est la racine carrée de n qui est à prendre en compte pour extraire les nombres premiers Ératosthène dans cette première partie...
T'as rien lu enfaite ?
eratosthenes n =
finitePrimeNumbers r
where r = floor . sqrt $ 2*(fromIntegral n) -- <------------
Comme indiqué, j'ai cherché ici à convertir ce qui est déjà fait en Python. C'est justement parce que je ne vais pas m'amuser à refaire expressément chaque étape entre $\sqrt{n}$ et $\sqrt{2\times n}$, que je détaille le plus possible ce qu'il se passe pour que tu puisses ensuite t'amuser à modifier des trucs comme tu le veux sans l'aide de personne.
Premiers Ératosthène que l'on va ensuite utiliser, dans la deuxième et troisième partie, afin de cribler : la liste "ou tableau " de 1,1,1......< n//30 .
Tout vient à point à qui sait attendre.
- LEG
- 07-11-2022 07:44:21
Bonjour
@rareStrophe.
ok pour tes explications afin de rendre le programme plus rapide ...(je n'y connais strictement rien en programmation) mais je comprends tes explications...
Ceci dit : gagner du temps sur cette première partie du programme de la def eratostene(n): qui énumère les nombres premiers $P\leqslant\sqrt(n)$
permettra de gagner du temps, dans la deuxième et troisième partie ...
Mais pourquoi avoir extrait tous les nombres premiers < 3000 , pour comparer les vitesses (éfficacité) des deux langages de programmation je suppose suite à tes explications....
N'oublies pas que pour $n = 999 999 999$ , c'est la racine carrée de $n$ qui est à prendre en compte pour extraire les nombres premiers Ératosthène dans cette première partie...
Premiers Ératosthène que l'on va ensuite utiliser, dans la deuxième et troisième partie, afin de cribler : la liste "ou tableau " de 1,1,1......< n//30 .
Exemple :
Donnez N: 3000
[7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73] premiers Ératosthène < racine de 3000
crible Ératosthène : [1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0]
Nombre premiers criblés famille 7 : 55 ----- 0.0
crible É ET G: [0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0]
Nombres P' non congru 2n[pi] ou couple P'+q = 2N, de (i) à 3000 famille 7 : 18 ----- 0.0
- rareStrophe
- 06-11-2022 22:03:32
Partie B : le portage, un long processus
La cour des grands
Un outil indispensable d'Haskell est cabal. cabal est ce qu'on pourrait appeler un gestionnaire de projet. Il va tout faire pour nous : gérer les dépendances, gérer la compilation, l’exécution, etc… Pour utiliser ce merveilleux outil, rendez-vous un dossier vide (nous choisirons ici d’appeler ce dossier crible) et exécutez la commande suivante :
$ cabal init
crible_E
crible_G
- rareStrophe
- 06-11-2022 19:38:54
Partie A : un monde à découvrir
Un langage de programmation tout en un
Le langage de programmation Haskell est en quelque sorte une plateforme toute en un. Une fois celui-ci installé, nous retrouverons sur notre ordinateur les quelques outils suivants :
GHC : The Glasgow Haskell Compiler ;
GHCi : L'interpreteur interactif ;
Les paquets Haskell les plus utiles ;
Un gestionnaire de projet.
Pour installer Haskell, deux options s'offrent à vous, le télécharger depuis le site du projet ou l'installer depuis le gestionnaire de paquet de votre système d'exploitation préféré :
# Pour Ubuntu
$ apt-get install ghc
# Pour macOS
$ brew install ghc
Pour s'assurer que tout fonctionne, demandons à ghc, le compilateur d'Haskell, de nous afficher son numéro de version. Ceci se réalise à l'aide de la commande qui suit :
$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 9.2.4
Le numéro de version pouvant évidemment varier selon votre installation.
Étant donné qu'à ce stade tout devrait fonctionner, créons d’emblée notre premier programme : le bien connu "hello, world!". Pour ce faire, ouvrons notre éditeur de texte préféré afin d'y écrire le code suivant :
que nous allons enregistrer dans un fichier main.hs.
Afin d’exécuter ce programme, nous allons devoir le compiler. La compilation consiste à transformer un programme textuel adapté à la compréhension des humains, du moins ceux formés pour ça, en un programme exécutable composé de 0 et de 1, adapté à la compréhension de l'ordinateur afin que ce dernier sache quelles opérations utiliser pour réaliser les tâches qui lui sont demandées.
Pour ce faire, ouvrez votre terminal et placez-vous dans le dossier contenant le fichier main.hs que vous venez de créer. Lorsque vous y êtes, lancez la commande suivante
$ ghc main.hs
[1 of 1] Compiling Main
Linking main ...
Bravo ! Vous venez d'obtenir votre premier programme en Haskell ! Vous voyez, ce n'était pas bien difficile ! À présent, il ne nous reste plus qu'à l'exécuter. Pour ce faire, tout en restant dans le même dossier, lancez la commande suivante :
$ ./main
"hello, world!"
Il nous est déjà possible de remarquer deux trois faits intéressants.
La ligne
-- Mon premier programmen'a pas été exécuté. Ceci est dû au fait que -- est la marque démarrant un commentaire qui sera ignoré par le compilateur.
Comme en C, C++, Java, Rust, ou encore Python, la fonction main est le point d'entré disant au compilateur où démarrer le programme.
La fonction print affiche les guillemets autour de notre chaine de caractères. Nous expliquerons ce dernier fait plus loin.
Vous vous demandez peut-être s'il est possible de demander au compilateur d'enregistrer l'exécutable dans un fichier au nom spécifique. Sachez que c'est effectivement possible avec -o. Pour ce faire, procédez ainsi :
$ ghc main.hs -o hello
[1 of 1] Compiling Main
Linking hello ...
Vous pouvez alors exécuter le programme comme suit :
$ ./hello
"hello, world!"
Intéressons-nous à présent au deuxième outil que nous utiliserons dans ce premier post : ghci. Comme indiqué dans l'introduction, ghci est un interpréteur intéractif, c'est-à-dire qu'il exécutera chacune de nos lignes de code au fur et à mesure que nous lui donnerons. Pour lancer ghci rien de plus simple :
$ ghci
ghci> _
Comme pour n'importe quel interpréteur, nous pouvons donc donner du code à ghci afin qu'il l'exécute. Voici quelques exemples :
ghci> 1 + 1
2
ghci> 2*2
4
ghci> 2^1024
179769313486231590772930519078902473361797697894230657273430081157732675805500963132708477322407536021120113879871393357658789768814416622492847430639474124377767893424865485276302219601246094119453082952085005768838150682342462881473913110540827237163350510684586298239947245938479716304835356329624224137216
Comme nous pouvons le voir, ghci exécute nos lignes de codes sans se poser de question tant que celles-ci sont valides et font sens pour lui. Les deux premiers exemples montrent qu'il est possible d'ajouter ou omettre les espaces non significatifs. Le troisième exemple montre un fait surprenant pour une personne venant d'un autre langage de programmation. Haskell est capable de gérer de nombres extrêmement grands ! En effet, nous pouvons même aller plus loin, par exemple :
ghci> 2^8192
1090748135619415929462984244733782862448264161996232692431832786189721331849119295216264234525201987223957291796157025273109870820177184063610979765077554799078906298842192989538609825228048205159696851613591638196771886542609324560121290553901886301017900252535799917200010079600026535836800905297805880952350501630195475653911005312364560014847426035293551245843928918752768696279344088055617515694349945406677825140814900616105920256438504578013326493565836047242407382442812245131517757519164899226365743722432277368075027627883045206501792761700945699168497257879683851737049996900961120515655050115561271491492515342105748966629547032786321505730828430221664970324396138635251626409516168005427623435996308921691446181187406395310665404885739434832877428167407495370993511868756359970390117021823616749458620969857006263612082706715408157066575137281027022310927564910276759160520878304632411049364568754920967322982459184763427383790272448438018526977764941072715611580434690827459339991961414242741410599117426060556483763756314527611362658628383368621157993638020878537675545336789915694234433955666315070087213535470255670312004130725495834508357439653828936077080978550578912967907352780054935621561090795845172954115972927479877527738560008204118558930004777748727761853813510493840581861598652211605960308356405941821189714037868726219481498727603653616298856174822413033485438785324024751419417183012281078209729303537372804574372095228703622776363945290869806258422355148507571039619387449629866808188769662815778153079393179093143648340761738581819563002994422790754955061288818308430079648693232179158765918035565216157115402992120276155607873107937477466841528362987708699450152031231862594203085693838944657061346236704234026821102958954951197087076546186622796294536451620756509351018906023773821539532776208676978589731966330308893304665169436185078350641568336944530051437491311298834367265238595404904273455928723949525227184617404367854754610474377019768025576605881038077270707717942221977090385438585844095492116099852538903974655703943973086090930596963360767529964938414598185705963754561497355827813623833288906309004288017321424808663962671333528009232758350873059614118723781422101460198615747386855096896089189180441339558524822867541113212638793675567650340362970031930023397828465318547238244232028015189689660418822976000815437610652254270163595650875433851147123214227266605403581781469090806576468950587661997186505665475715792896
Bien évidement, vous pouvez mettre le nombre arbitrairement élevé de votre choix. En réalité, là où d'autres langages de programmation considèrent les nombres comme étant des entités vivantes dans un espace délimité en mémoire, int8 pour des entiers sur 8 bits, int16 pour des entiers sur 16 bits, int32 pour des entiers sur 32 bits, etc… Haskell, dispose d'une entité Integer qui se rapproche de la définition mathématique de nombre entier : n'importe quelle suite de chiffre de n'importe quelle longueur. Nous expliquerons dans le prochain post les différences avec les entiers que l'on retrouve dans d'autres langages de programmation.
ghci> x = 10 + 5 - 2
ghci> x
13
ghci> carre x = x*x
ghci> carre 12
144
Bien entendu, ghci gère les variables et les fonctions où, à nouveau, il est possible d'ajouter ou omettre des espaces non significatifs.
ghci est de plus un formidable outil en mesure d'importer les fonctions de vos fichiers afin de les utiliser. Pour ce faire rendez-vous dans le dossier contenant un de vos fichiers Haskell. Nous supposerons ici que nous voulons importer le fichier main.hs. Lancez alors ghci et effectuez les manipulations suivantes
ghci> :l main.hs
[1 of 1] Compiling Main
Ok, modules loaded: Main.
Maintenant que tout a été chargé, il est possible d'exécuter la fonction main que nous avons écrite plus tôt
ghci> main
"hello, world!"
Petit exercice : Modifier la fonction main dans main.hs de sorte que vous puissiez afficher "Bonjour [votre pseudo]" dans ghci.
Comme nous ne savons toujours pas composer des chaines de caractères avec des variables, nous devons nous contenter d'écrire une fonction à usage unique :
puis nous chargeons et lançons le tout dans ghci
ghci> :l main.hs
ghci> main
"Bonjour rareStrophe"
Finalement, pour quitter ghci, tapez ce qui suit
ghci> :q
Leaving GHCi.
Les bases de la programmation fonctionnelle et d'Haskell
Nous savons à présent utiliser les outils de base d'Haskell, il est donc grand temps d'apprendre à programmer avec celui-ci. Toute fois, avant de s’aventurer plus loin, il va nous falloir nous poser une question primordiale : qu'est-ce qu'une application ?
Si vous avez fait quelques maths, vous savez connaissez alors la définition suivante:
Définition: Une relation $f$ d'un ensemble source $E$ vers un ensemble but $F$ est une application, si et seulement si, pour tout élément $x$ de $E$, il y a un unique élément $y$ de $F$ tel que le couple $(x,y)$ soit lié par $f$.
qu'il est possible réécrire de manière plus digeste comme cela :
Définition v2: Une application $f$ d'un ensemble source $E$ vers un ensemble but $F$ est une relation qui à tout élément $x$ de $E$ associe un unique élément $y$ de $F$. On note alors $y=f(x)$.
Mais alors pourquoi parler d'application ? Cela est dû au fait que la programmation fonctionnelle fait en réalité plus référence à ce qu'on appelle application en français. Ainsi, les langages de programmations fonctionnels et a fortiori Haskell, suivent tous cette définition que l'on peut aussi désigner à l'aide des règles suivantes :
Toute application doit prendre un argument ;
Toute application doit retourner une valeur ;
Toute valeur retournée par une application doit être unique.
Cette dernière règle est connue sous le doux nom de principe de transparence référentielle.
Néanmoins, afin de ne pas être trop perdu avec les différentes ressources disponibles,
admettons à présent que le mot fonction correspond à une application.
Commençons avec l'exemple le plus simple qui soit, la fonction identité. Pour ce faire, lancez ghci et entrez le code suivant :
ghci> identity x = x
Cette fonction identity accepte un argument x et nous le retourne sans rien y faire.
ghci> identity "Bonjour"
"Bonjour"
ghci> identity 12
12
ghci> identity [0,1,2,3,4,5,6,7,8,9]
[0,1,2,3,4,5,6,7,8,9]
Nous remarquons ici une des premières forces du langage Haskell : l'inférence de types. En effet, comme nous pouvons le voir, il nous est possible de donner à la fonction identity n'importe quel argument, qu'il soit un nombre, une chaine de caractères ou encore une liste. Le compilateur sera en mesure de déterminer le bon type à appliquer le moment venu sans que l'on ait besoin de l'expliciter nous-même.
Dirigeons nous à présent vers l'utilisation de variables. Pour cela, écrivons les lignes suivantes dans le fichier main.hs :
x = 1
x = 3.14
que nous compilons ensuite de la manière suivante :
$ ghc main.hs
[1 of 1] Compiling Main ( main.hs, main.o )
main.hs:2:1: error:
Multiple declarations of ‘x’
Declared at: main.hs:1:1
main.hs:2:1
|
2 | x = 3.14
| ^
Horreur, cela ne compile pas ! Au vue de ce que l'on sait déjà, saurez-vous expliquer pourquoi ?
Il faut savoir que les variables en Haskell ne sont en rien… variable ! Si celles-ci l'étaient, cela violerait le principe d'unicité. Visualisez donc une variable Haskell comme une définition d'une valeur donnée. Un peu comme on définit $\pi = 3.1415...$. Il ne viendrait à l'idée de personne de modifier la valeur de $\pi$. C'est en quelque sorte ce qu'il se passe en Haskell.
Petite note subsidiaire:
Comme il est assez pénible de relancer l'interpréteur ghci
à chaque fois que l'on veut faire des testes quelconques,
celui-ci permet de redéfinir les variables.
Ainsi, le code précédent fonctionne dans ghci.
À la conquête des nombres premiers !
Mettons à présent à profit tout ce que nous avons vu plus haut afin de générer la liste des nombres premiers jusqu'à $\lfloor\sqrt{2\times n}\rfloor$.
Premièrement, commençons par mettre à profit le côté lazy d'Haskell afin de ne pas nous soucier des ressources. Ainsi donc, créons une liste infinie de nombre premier.
Afin de tester ce bout de code, il nous faut charger le fichier dans ghci et lancer appeler la fonction. Pour ce faire, enregistrez le code précédant dans un fichier primes.hs puis lancez ghci. Une fois ceci fait, charger le contenu de ce fichier primes.hs dans ghci de la manière suivante :
ghci> :l primes.hs
[1 of 1] Compiling Main ( primes.hs, interpreted )
Ok, one module loaded.
ghci> sieve
<interactive>:2:1: error:
• No instance for (Show ([Integer] -> [Integer]))
arising from a use of ‘print’
(maybe you haven't applied a function to enough arguments?)
• In a stmt of an interactive GHCi command: print it
Mais que se passe-t-il ? Pourquoi une erreur s'affiche-t-elle ? Eh bien cela est dû au fait que notre fonction sieve s'attend à recevoir une liste en paramètre. Nous expliquerons pourquoi juste après. Pour l'heure, écrivons une nouvelle fonction qui appelle sieve et lui passe en paramètre la liste infinie [2..] de la façon suivante :
primeNumbers = sieve [2..]
Nous pouvons à présent utiliser la fonction primeNumbers comme suit:
ghci> primeNumbers
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73,79,83,89,97,101,103,107,109,113,127,131,137,139,149,151,157,163,167,173,179,181,191,193,197,199,211,223,227,229,233,239,241,251,257,263,269,271,277,281,283,293, ....]
Comme nous pouvons le voir, nous obtenons bel et bien une liste infinie ne contenant que les nombres premiers. C'est très bien, mais vous vous retrouvez sans doute pantois avec votre terminal inaccessible. Pour interrompre cette interminable liste, faites ctrl-c.
Afin de ne pas attendre indéfiniment la liste infinie de nombre premiers, choissons de n'en garder que quelques-un. Pour ce faire, utilisons la fonction Haskell take :
ghci> take 20 primeNumbers
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71]
Avant d'aller plus loin, essayons de comprendre comment fonctionne la fonction sieve :
Haskell applique le pattern matching x:xs à cette liste : ainsi pour la liste [2..], x=2 et xs=[3,4,5,...]; avant d'évaluer ce qu'il reste de xs de la façon suivante
Petite subtilité ici, xp `mod` x > 0 est ce qu'on appelle un filtre.
C'est à dire que l'on filtre les éléments de sorte à ne garder que ceux
qui répondent à la condition $xp > 0 [x]$.
On évalue donc xs qui commence avec xp=3 or xp=3 passe le filtre. On se retrouve à présent à passer récursivement la liste [3..] à sieve.
x:xs avec x=3 et xs=[4,5,6,...].
Rebelote
et ainsi de suite. Finalement, on trouve tous les nombres premiers par récursion.
Intéressons-nous à présent à récuperer les nombres premiers qui nous intéressent, ceux qui sont inférieurs ou égaux à $\lfloor\sqrt{2\times n}\rfloor$. Pour ce faire, utilisons cette fois-ci la fonction Haskell takeWhile au sein de la fonction suivante :
Cette fonction eratosthenes s'utilise alors comme suit :
ghci> eratosthenes 3000
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,73]
À quoi ressemble donc notre code jusqu'à maintenant ? Eh bien, il est composé des trois lignes suivantes :
Comment cela peut aussi bien fonctionner ? Pour cela il nous faut expliquer takeWhile. takeWhile est une fonction bien utile qui retourne une liste composer de tout les éléments correspondant au filtre passé en paramètre. Ce filtre est, ici, <= floor . sqrt $ 2*n, ce que l'on peut lire
prend tous les nombres dans la liste primeNumbers tant que ceux-ci sont inférieurs ou égaux à $\lfloor\sqrt{2\times n}\rfloor$; arrête ensuite.
Arrêtons-nous un instant et demandons-nous si ce programme s'effectue rapidement. Pour ce faire, compilons le programme suivant à l'aide de ghc :
À présent, testons !
❯ hyperfine --warmup 3 --min-runs 10 "./eratosthenes 3000"
Benchmark 1: ./eratosthenes 3000
Time (mean ± σ): 18.2 ms ± 1.1 ms [User: 1.8 ms, System: 6.2 ms]
Range (min … max): 15.5 ms … 20.2 ms 140 runs
18 ms pour générer les nombres premiers jusqu'à $\lfloor\sqrt{2\times 3000}\rfloor$...
❯ hyperfine --warmup 3 --min-runs 10 "./eratosthenes 999999999"
Benchmark 1: ./eratosthenes 999999999
Time (mean ± σ): 404.6 ms ± 4.4 ms [User: 385.9 ms, System: 8.9 ms]
Range (min … max): 396.7 ms … 409.1 ms 10 runs
404 ms pour générer les nombres premiers jusqu'à $\lfloor\sqrt{2\times 999999999}\rfloor$ ! Ça va pas du tout ! C'est beaucoup trop lent ! Peut-on rendre tout ceci plus rapide ? Oui, c'est possible ! Nous allons voir comment dans le post suivant.
- rareStrophe
- 06-11-2022 18:09:57
Parfait @yoshi !
Du coup, je vous propose de réaliser ce portage deux temps (ou deux messages) :
L'apprentissage d'un peu d'Haskell et l'utilisation de cabal.
Ceci au travers de la création naïve de l'ensemble des nombres premiers ainsi que de l'ensemble (la liste) eratosthene qui nous servira à créer les cribles plus tard. Un petit peu de réflexion sur notre code naïf et sur quelques possibilités de profilage.Le portage à proprement parlé du programme Python en Haskell.
Pour ce faire, nous utiliserons tous les outils qu'Haskell met à notre disposition : dépendances à des paquets, programmation fonctionnelle, optimisation du compilateur, etc.
Notre but sera de réaliser le programme le plus rapide possible en le moins de temps possible afin que cela reste digeste. Bien entendu, n'étant pas un expert Haskell avec 20 ans de pratique, il restera tout à fait possible d'améliorer ce que je proposerai.
Pourquoi faire comme ça ?
Tout simplement car j'escompte expliquer du mieux que j'en suis capable ce qu'il se passe, de sorte que n'importe qui puisse lire ces messages comprendre le code et l’exécuter en toute connaissance de cause.
Rendez-vous donc au prochain post !
- yoshi
- 06-11-2022 17:52:04
Ave,
Correction faite.
Moi non plus, je n'aime pas qu'on écorche les noms...
@+








