Page 1 sur 1

Fonction aléatoire sur un intervalle

Publié : mer. 12/sept./2012 13:01
par Golfy
J'ai lu (dans un post "houleux") qu'un programmeur avait besoin d'une fonction random plus pratique que la fonction de base.
Son besoin était :
1) pouvoir choisir des nombres négatifs (random(max) propose entre 0 et max)
2) pouvoir conserver ou non la valeur zéro sans devoir ajouter 1 (qui nécessite alors de soutraire 1 à max).

L'exercice était simple mais outre les réponses inutiles, une réponse possible de procédure était manquante (et le post est désormais verrouillé). Voici la plus courte des procédures je crois :lol:

Code : Tout sélectionner

; procedure de génération de nombre aléatoire dans un intervalle (bornes incluses)
; by Golfy (2012-09)
;
Procedure.i rnd(min.i, max.i)
	ProcedureReturn Random(max.i-min.i)+min.i
EndProcedure

For t=1 To 50
	Debug Str(rnd(0,8))+"               "+ Str(rnd(-10,10))+"               "+ Str(rnd(-20,10))
Next t
Ce code permet de choisir son intervalle, seule contrainte : saisir les nombres dans l'ordre (les bornes sont incluses dans le résultat renvoyé).

1) rnd(-10,10) renvoie des nombres entre -10 (donc négatifs) et 10
2) rnd(1,5) renvoie des nombres entre 1 et 5

Re: Fonction aléatoire sur un intervalle

Publié : jeu. 13/sept./2012 0:46
par G-Rom
Merci Golfy , toujours pratique d'avoir ce genre de fonction sous la main.
c'est du "tout prêt sans réfléchir" :mrgreen:

Re: Fonction aléatoire sur un intervalle

Publié : jeu. 13/sept./2012 9:22
par Le Soldat Inconnu
juste pour vérifier le que le random répartit bien le retour entre le min et le max

Code : Tout sélectionner

; procedure de génération de nombre aléatoire dans un intervalle (bornes incluses)
; by Golfy (2012-09)
;
Procedure.i rnd(min.i, max.i)
		ProcedureReturn Random(max.i-min.i)+min.i
EndProcedure


Dim Cpt(9)

For x = 1 To 10000000
	
	Aleatoire = rnd(0, 9)
	Cpt(Aleatoire) = Cpt(Aleatoire) + 1
	
Next

For x = 0 To 9
	Debug Str(x) + " = " + Str(Cpt(x))
Next

Re: Fonction aléatoire sur un intervalle

Publié : jeu. 13/sept./2012 10:02
par Backup
L'exercice était simple mais outre les réponses inutiles, une réponse possible de procédure était manquante
il s'agit de ce post :
http://www.purebasic.fr/french/viewtopi ... om&start=0

et nous sommes quand meme plusieurs a avoir apporter une solution (y compris en procedure ;) )
a te lire , on pourrai croire qu'aucune reponses UTILE n'a été apporté , ....

Reponse de Ar-s

Code : Tout sélectionner

For i = 1 To 5
  EssayeEncore:
  R = Random(i)
  If R = 0
    Goto EssayeEncore
  EndIf
 
  neg = Random(1)
  If neg = 0
    R - (2*R)
  EndIf
 
  Debug R
 
Next
Reponse de Comtois :

Code : Tout sélectionner



Pour un nombre négatif compris entre -20 et -1
R = -1 - Random(19)
Reponse de TazNormand :

Code : Tout sélectionner

For i = 1 To 20
   R = Random(20)+1
      
   neg = -R
      
   Debug R
   Debug neg
Next

Reponse de Dobro ( en procedure ) ;)
voici une fonction qui permet de choisir un chiffre aleatoire
parmis une liste de chiffre positif ou negatif

cette liste partira du parametre "a" jusqu'au parametre "b"
pour l'exemple de -10 a 10

Code : Tout sélectionner

Declare  rando(a,b)

debug rando(-10,10) ; ici on va choisir parmis une liste qui va de -10 a 10  ;o)

procedure rando(a,b)
   ; By Dobro
   ; info : la valeur du parametre "a" doit etre inferieur a "b"
   ; ****
   ; prepare la liste de numéros voulue
   for x=a to b
      liste.s=liste.s+str(x)+","
   next x
   calldebugger
   ; maintenant on choisi une valeur de cette liste au hasard
   pos=random(CountString(liste.s,","))-1 ; on recup le nombre de virgules (donc le nombre de chiffre de la chaine-1...la virgule de fin)..et on tire un element au hasard
   valeur.s=stringfield(liste.s,pos,",") ; on extrait de la chaine la valeur tiré au hasard
   ProcedureReturn val(valeur)
endprocedure

; EPB
Autre reponse de Dobro
autre fonction , qui retourne un chiffre au hasard ,(positif ou negatif) mais sans plage

Code : Tout sélectionner

Declare  rando2(a)

for i=1 to 10 ; on va tirer 10 chiffre au hasard
   debug rando2(10) ;
next i
procedure rando2(a)
   ; By Dobro
   ; retourne un chiffre aleatoire positif ou negatif
   x=random(a) ; le chiffre qu'on tire au hasard
   de=random(1) ; le dé qui sert a choisir aleatoirement si ça va etre positif ou négatif
   if de=0 ; le chiffre sera négatif
      x=-x
   endif
   ProcedureReturn x
endprocedure
;

; EPB


voila voila :)

Re: Fonction aléatoire sur un intervalle

Publié : jeu. 13/sept./2012 10:06
par Ar-S
Un des charmes majeur de la prog en ce qui me concerne, trouver moult solutions pour arriver au même résultats.

Re: Fonction aléatoire sur un intervalle

Publié : jeu. 13/sept./2012 10:07
par Backup
c'est clair :)

Re: Fonction aléatoire sur un intervalle

Publié : jeu. 13/sept./2012 10:10
par falsam
Réponse de ..... moi :mrgreen: j'ai une préférence pour la solution de Golfy beaucoup plus sexy dans sa présentation et tellement plus courte.

Code : Tout sélectionner

Procedure.i rnd(min.i, max.i)
   ProcedureReturn Random(max.i-min.i)+min.i
EndProcedure

Re: Fonction aléatoire sur un intervalle

Publié : jeu. 13/sept./2012 11:01
par Ar-S
Golfy a écrit : Ce code permet de choisir son intervalle, seule contrainte : saisir les nombres dans l'ordre (les bornes sont incluses dans le résultat renvoyé).
Avec un petite vérif on annule cette contrainte. ne jamais lésiner sur les vérifications dans les procédures !

Code : Tout sélectionner

Procedure.i rnd(min.i, max.i)
  if min = max
procedurereturn min
endif

If min > max
    ProcedureReturn Random(mix.i-max.i)+max.i
  Else
    ProcedureReturn Random(max.i-min.i)+min.i
  EndIf
EndProcedure
Ainsi peut donner comme consigne pour sa proce
rnd(valeur1, valeur2) sans se soucier de l'ordre.

Re: Fonction aléatoire sur un intervalle

Publié : jeu. 13/sept./2012 12:08
par Fred
Si min = max, tu devrais renvoyer 'min', pas 0 :)

Re: Fonction aléatoire sur un intervalle

Publié : jeu. 13/sept./2012 12:20
par Golfy
Dobro a écrit :
L'exercice était simple mais outre les réponses inutiles, une réponse possible de procédure était manquante
et nous sommes quand meme plusieurs a avoir apporter une solution (y compris en procedure ;) )
a te lire , on pourrai croire qu'aucune reponses UTILE n'a été apporté , ....

voila voila :)
Mes excuses si ma phrase te fait penser cela (probablement la redondance du mot réponse, j'aurais écrire :" outre les réponses hors-sujets, une solution possible...") :oops:
En effet, c'est ce qui m'a le plus choqué sur le post correspondant (les réponses hors-sujets). Le forum anglais semble plus sain... :(

Donc loin de moi l'idée que des solutions n'avaient pas été astucieusement proposées mais juste l'envie de contribuer à la diversité des solutions :)

J'ai deux leit-motiv dans la vie :
ce qui ce conçoit bien, s'énonce clairement (grâce à ça, j'ai pu par exemple améliorer mon code pour PB_Velbus-server d'une version à l'autre : en simplifiant... je remecie tout les jours mon prof d'électronique qui nous répétait cette phrase tout les jours :))
Collaborative spirit : mettre de l'énergie à résoudre les défis de la vie plutôt qu'à gérer des problèmes d'ego (y compris les siens) :)

Re: Fonction aléatoire sur un intervalle

Publié : jeu. 13/sept./2012 12:28
par Golfy
Le Soldat Inconnu a écrit :juste pour vérifier le que le random répartit bien le retour entre le min et le max

Code : Tout sélectionner

; procedure de génération de nombre aléatoire dans un intervalle (bornes incluses)
; by Golfy (2012-09)
;
Procedure.i rnd(min.i, max.i)
		ProcedureReturn Random(max.i-min.i)+min.i
EndProcedure

Dim Cpt(9)
For x = 1 To 10000000
	Aleatoire = rnd(0, 9)
	Cpt(Aleatoire) = Cpt(Aleatoire) + 1
Next

For x = 0 To 9
	Debug Str(x) + " = " + Str(Cpt(x))
Next
Excellent cet algo de répartition : je n'avais pas cherché dans la bonne direction... ça devrait me servir pour de la supervision de trames ! merci
[Edit] à condition de n'avoir que des nombres positifs :oops:

Re: Fonction aléatoire sur un intervalle

Publié : jeu. 13/sept./2012 13:29
par Le Soldat Inconnu
pour des nombres négatif, tu peux partir sur une MAP

Code : Tout sélectionner

; procedure de génération de nombre aléatoire dans un intervalle (bornes incluses)
; by Golfy (2012-09)
;
Procedure.i rnd(min.i, max.i)
				ProcedureReturn Random(max.i-min.i)+min.i
EndProcedure

NewMap  Cpt()

For x = 1 To 1000000
		Aleatoire.s = Str(rnd(-10, 10))
		Cpt(Aleatoire) = Cpt(Aleatoire) + 1
Next

For x = -10 To 10
		Debug Str(x) + " = " + Str(Cpt(Str(x)))
Next
ou sinon, avec un offset

Code : Tout sélectionner

; procedure de génération de nombre aléatoire dans un intervalle (bornes incluses)
; by Golfy (2012-09)
;
Procedure.i rnd(min.i, max.i)
				ProcedureReturn Random(max.i-min.i)+min.i
EndProcedure

Dim  Cpt(20)

For x = 1 To 1000000
		Aleatoire = rnd(-10, 10)
		Cpt(Aleatoire + 10) = Cpt(Aleatoire + 10) + 1
Next

For x = -10 To 10
		Debug Str(x) + " = " + Str(Cpt(x + 10))
Next

Re: Fonction aléatoire sur un intervalle

Publié : jeu. 13/sept./2012 16:11
par Ar-S
Quitte à simplifier la syntaxe :

Changer
Cpt(Aleatoire + 10) = Cpt(Aleatoire + 10) + 1
devient
Cpt(Aleatoire + 10) + 1 suffit

Petit rappel :
N'oubliez pas que pure basic permet ce genre d'incrémentation directe.

a$ = "toto"
pour ajouter "titi" à a$ ce n'est pas utile de ré-écrire

a$ = a$ + "titi"
Vous pouvez simplement mettre
a$ + titi$

On fait bien comme on veut (ou comme on a l'habitude) mais c'est bien de le savoir.
fred a écrit :Si min = max, tu devrais renvoyer 'min', pas 0 :)
C'est pas faux. Le 0 est plus là pour dire "Hum y'a une couille dans l'gigot" :) Mais c'est vrai que renvoyer une des 2 valeurs est plus juste.

Re: Fonction aléatoire sur un intervalle

Publié : ven. 14/sept./2012 8:19
par Golfy
Merci LSI : je ne connaissais pas les MAP (je pensais que c'était lié aux fonctions 3D)
C'est vraiment génial et simple... comme beaucoup de choses en PureBasic :)