💾 Archived View for gem.ortie.org › gemlog › 2023-04-16.gmi captured on 2024-08-18 at 17:53:06. Gemini links have been rewritten to link to archived content

View Raw

More Information

⬅️ Previous capture (2023-04-19)

-=-=-=-=-=-=-

💻 FORTH et la randomisation : quelle précision ?

Certains FORTH peuvent avoir un mot définissant une fonction de randomisation, mais il peut être amusant de la créer soi-même, c'est un peu le principe de FORTH...

J'en ai trouvé une toute faite :

VARIABLE rand
HERE rand !

: random rand @ 31421 * 6927 + DUP rand ! ; 
: rnd ( u1 -- u2 ) random random UM* NIP 10 mod ;

ça fonctionne plutôt bien, seulement certains FORTH ne possèdent pas le mot UM* (multiplication sur les valeurs doubles non signée si je ne m'abuse)

J'ai donc modifié le mot 'rnd' comme suit :

: rnd ( u1 -- u2 ) random random - random * ABS 10 /MOD + random + random * HERE + ABS 10 /MOD - ABS 10 MOD ;

C'est un bidouillage un peu naif, mais ça fonctionne relativement bien, et la répartition semble similaire d'avec l'autre :

dans le premier cas, sur 2600 lettres, on a une répartition allant de 80 à 120.

dans le second cas, on a une répartition allant de 75 à 130 lettres environ (avec gforth, peut-être que d'autres FORTH auront du mal à gérer les grands nombres)

Les mots pour générer cela :

\ génère une lettre entre A et Z
: lettre rnd 10 * rnd + 
 DUP 
 65 < IF DROP RECURSE ELSE 
   DUP 90 > IF DROP RECURSE ELSE  
   THEN THEN
;

: lettres ( nb -- out )
 1 DO
 lettre EMIT CR
 LOOP
;

Pour tester l'occurence des lettres, j'utilise ce script :

gforth random_words.fs -e '2600 lettres cr bye' | sort | uniq -c | sort -n

j'ai comparé avec la fonction random de python3, avec ce code :

import string
import random

for x in range(1,2600):
	truc=random.choice(string.ascii_uppercase)
	print(truc)

ça donnera par exemple ça, ce qui est dans une distribution similaire à ce qu'il y a avec les fonctions FORTH plus haut :

python3 random_words.py  | sort | uniq -c | sort -n
     74 C
     82 U
     86 Y
     88 H
     89 L
     90 I
     92 V
     93 A
     94 S
     95 D
     95 K
     95 P
     98 T
    100 R
    101 F
    102 Z
    103 O
    105 Q
    106 X
    107 N
    115 G
    115 J
    115 W
    116 B
    121 E
    122 M

C'est assez similaire aux résultats de FORTH ci-dessus, donc je suppose qu'on ne peut pas faire mieux en FORTH...

Je me demande s'il serait possible d'obtenir une distribution encore plus proche de 100 pour chaque lettre...

Pour mettre les choses en perspective, sur des nombres plus importants, python est plus performant (avec 2 600 000 au lieu de 2 600) :

  99440 O
  99620 F
  99630 Z
  99689 J
  99711 D
  99797 A
  99807 U
  99833 M
  99890 K
  99924 Y
  99992 G
  99993 V
 100013 R
 100041 I
 100060 P
 100071 T
 100081 L
 100113 Q
 100129 B
 100174 N
 100178 H
 100207 C
 100245 E
 100336 S
 100441 W
 100584 X

avec la deuxième fonction 'rnd' (ma fonction stupide et naïve n'utilisant pas UM*), la distribution est moins équilibrée sur les grands nombres :

  91578 W
  91597 O
  91627 M
  91736 G
  91847 S
  91932 C
  91943 E
  92003 K
  92033 A
  92083 U
  92101 I
  92222 Q
  92827 Y
 107474 Z
 107487 B
 107601 D
 107609 J
 107620 P
 107809 V
 108009 L
 108240 T
 108265 N
 108316 X
 108320 H
 108794 F
 108926 R

La première fonction "rnd", avec UM*, est similaire au résultat de python ;

  99541 R
  99641 F
  99655 G
  99729 X
  99754 B
  99773 K
  99778 Z
  99816 Y
  99829 U
  99854 T
  99865 O
  99963 I
  99984 A
  99986 S
 100013 L
 100054 W
 100103 P
 100150 M
 100169 J
 100181 D
 100217 N
 100270 H
 100303 Q
 100354 C
 100407 E
 100610 V

Je suis certain que vous voulez maintenant savoir quelle est la différence de performance entre Python et FORTH.

Forth (avec UM*):

real    0m2,751s
user    0m2,992s
sys     0m0,145s

Python a pris 38,5 % de temps en plus que FORTH :

real    0m3,810s
user    0m4,485s
sys     0m0,045s

../docs/005_forth.gmi

#informatique

↩️ Index Gemlog

🏠 Index Accueil