Générer une liste de nombres réels aléatoires au moyen d'un dictionnaire

Magic_Doctor

XLDnaute Barbatruc
Bonjour,

Je voudrais dresser une liste de nombres réels aléatoires.
Pour ce faire, plutôt que de passer par une boucle interminable qui rempli, au fur et à mesure, chaque ligne d'un tableau de la feuille, j'ai préféré utiliser le dictionnaire : bien plus rapide et pas de doublons. J'ai cherché un algorithme pour les nombres aléatoires, mais j'avoue que celui que j'ai trouvé ne marche pas très fort car les nombres renvoyés dépassent largement les limites fixées :
VB:
Sub aleatoire()

Application.ScreenUpdating = False
Dim i As Integer, nb As Integer, a As Integer, b As Integer, dico As Object
Set dico = CreateObject("Scripting.Dictionary")
nb = 10  'nombre de lignes du tableau
a = -1  'limite inférieur
b = 1.75  'limite supérieure

For i = 1 To nb
    'Randomize 'faut-il ou pas le mettre ???
    dico(i) = Int(b - a + 1) * Rnd() + a 'bidouillage algorithmique
Next
[A2].Resize(dico.Count, 1) = Application.Transpose(dico.items)
Application.ScreenUpdating = True
End Sub

Merci d'avance pour toute aide.
 

job75

XLDnaute Barbatruc
Re : Générer une liste de nombres réels aléatoires au moyen d'un dictionnaire

Bonjour Magic_Doctor, mapomme, le forum,

La limite de 15 chiffres significatifs est une limite d'Excel.

Si l'on veut que les nombres aléatoires soient des nombres on ne peut donc rien faire.

Bien sûr si l'on veut générer des textes on pourrait concaténer plusieurs nombres aléatoires mais quel intérêt ?

Cela dit il faut en l'état compléter la fonction Aleatoire.

En effet le nombre maximum de nombres aléatoires créés est (LimSup - LimInf) * 10 ^ Virgule

Sur ton fichier si l'on a par exemple :

LimSup (M8) = 2, LimInf (M7) = 1, Virgule (ComboBox) = 0

la macro tournera indéfiniment...

Donc il faut ajouter un test pour arrêter tout :

Code:
Sub Aleatoire(LimInf As Double, LimSup As Double, plage As Range, Virgule As Byte)
'Dresse une liste de nombres aléatoires
'- LimInf : la plus petite valeur possible de la fourchette de nombres possibles
'- LimSup : la plus grande valeur possible de la fourchette de nombres possibles
'- Plage : plage où apparaissent les nombres aléatoires
'- Virgule : si = 0 --> nombres entiers
'            si > 0 --> détermine alors le nombre de décimales après la virgule
'job75 / Magic_Doctor

  Dim NbLgn As Long, dico As Object
  
  NbLgn = plage.Rows.Count 'nombre de lignes de la plage [Plage]
  If (LimSup - LimInf) * 10 ^ Virgule < NbLgn Then End 'arrête tout
  Set dico = CreateObject("Scripting.Dictionary")
  
  Randomize
  While dico.Count < NbLgn
    dico(Round((LimSup - LimInf) * Rnd + LimInf, Virgule)) = ""
  Wend
  plage = Application.Transpose(dico.keys)
End Sub
A+
 

job75

XLDnaute Barbatruc
Re : Générer une liste de nombres réels aléatoires au moyen d'un dictionnaire

Re,

Voici une solution avec concaténation :

Code:
Sub Aleatoire(LimInf As Double, LimSup As Double, plage As Range, Virgule As Byte)
'Dresse une liste de nombres aléatoires
'- LimInf : la plus petite valeur possible de la fourchette de nombres possibles
'- LimSup : la plus grande valeur possible de la fourchette de nombres possibles
'- Plage : plage où apparaissent les nombres aléatoires
'- Virgule : si = 0 --> nombres entiers
'            si > 0 --> détermine alors le nombre de décimales après la virgule
'job75 / Magic_Doctor

  Dim NbLgn As Long, dico As Object, x$, y$
  
  NbLgn = plage.Rows.Count 'nombre de lignes de la plage [Plage]
  If (LimSup - LimInf) * 10 ^ Virgule < NbLgn Then End
  Set dico = CreateObject("Scripting.Dictionary")
  
  Randomize
  While dico.Count < NbLgn
    x = Int((LimSup - LimInf) * Rnd + LimInf)
    y = ""
    If Virgule Then y = "." & Mid(Application.Round(Rnd, Virgule), 3)
    dico(x & y) = ""
  Wend
  plage = Application.Transpose(dico.keys)
End Sub
Les colonnes sont bien mises plus loin au format Texte :

Code:
With Selection
    .NumberFormat = "@"
Fichier joint.

A+
 

Pièces jointes

  • Limite Listes Nb Aléatoires(1).xlsm
    61.4 KB · Affichages: 36

ROGER2327

XLDnaute Barbatruc
Re : Générer une liste de nombres réels aléatoires au moyen d'un dictionnaire

Bonjour à tous.


Un autre bricolage...​


Bonne journée.


ℝOGER2327
#8010


Jeudi 12 Phalle 142 (Sainte Andouille, amphibologue - fête Suprême Quarte)
5 Fructidor An CCXXIII, 3,9556h - saumon
2015-W34-6T09:29:36Z
 

Pièces jointes

  • Copie de Limite Listes Nb Aléatoires.xlsm
    68.2 KB · Affichages: 43

mapomme

XLDnaute Barbatruc
Supporter XLD
Re : Générer une liste de nombres réels aléatoires au moyen d'un dictionnaire

Bonjour à tous :),

Comme j'avais aussi bricolé quelque chose, je le publie...

Edit : j'ai pompé le code de job75 :eek:
 

Pièces jointes

  • Limite Listes Nb Aléatoires-mpm1.xlsm
    45.9 KB · Affichages: 20
Dernière édition:

job75

XLDnaute Barbatruc
Re : Générer une liste de nombres réels aléatoires au moyen d'un dictionnaire

Re, salut Roger,

Ma macro du post #19 n'affichait pas les zéros non significatifs à la fin.

Pour toujours les afficher :

Code:
Sub Aleatoire(LimInf As Double, LimSup As Double, plage As Range, Virgule As Byte)
'Dresse une liste de nombres aléatoires
'- LimInf : la plus petite valeur possible de la fourchette de nombres possibles
'- LimSup : la plus grande valeur possible de la fourchette de nombres possibles
'- Plage : plage où apparaissent les nombres aléatoires
'- Virgule : si = 0 --> nombres entiers
'            si > 0 --> détermine alors le nombre de décimales après la virgule
'job75 / Magic_Doctor

  Dim NbLgn As Long, dico As Object, x$, y$
  
  NbLgn = plage.Rows.Count 'nombre de lignes de la plage [Plage]
  If (LimSup - LimInf) * 10 ^ Virgule < NbLgn Then End
  Set dico = CreateObject("Scripting.Dictionary")
  
  Randomize
  While dico.Count < NbLgn
    x = Int((LimSup - LimInf) * Rnd + LimInf)
    y = ""
    If Virgule Then y = Mid(Format(CDbl(Rnd), "0." & String(Virgule, "0")), 2)
    dico(x & y) = ""
  Wend
  plage = Application.Transpose(dico.keys)
End Sub
Nota : pour le calcul de y j'ai remplacé le point par le séparateur décimal de l'ordi.

Fichier (2).

A+
 

Pièces jointes

  • Limite Listes Nb Aléatoires(2).xlsm
    61.8 KB · Affichages: 20

job75

XLDnaute Barbatruc
Re : Générer une liste de nombres réels aléatoires au moyen d'un dictionnaire

Re,

Qui peut le plus peut le moins, ceci permet d'avoir jusqu'à 30 décimales :

Code:
Sub Aleatoire(LimInf As Double, LimSup As Double, plage As Range, Virgule As Byte)
'Dresse une liste de nombres aléatoires
'- LimInf : la plus petite valeur possible de la fourchette de nombres possibles
'- LimSup : la plus grande valeur possible de la fourchette de nombres possibles
'- Plage : plage où apparaissent les nombres aléatoires
'- Virgule : si = 0 --> nombres entiers
'            si > 0 --> détermine alors le nombre de décimales après la virgule
'job75 / Magic_Doctor

  Dim NbLgn As Long, dico As Object, x$, y$
  
  NbLgn = plage.Rows.Count 'nombre de lignes de la plage [Plage]
  If (LimSup - LimInf) * 10 ^ Virgule < NbLgn Then End
  Set dico = CreateObject("Scripting.Dictionary")
  
  Randomize
  While dico.Count < NbLgn
    x = Int((LimSup - LimInf) * Rnd + LimInf)
    y = ""
    If Virgule Then
      If Virgule < 16 Then
        y = Mid(Format(CDbl(Rnd), "0." & String(Virgule, "0")), 2)
      Else
        y = Mid(Format(CDbl(Rnd), "0." & String(15, "0")), 2)
        y = y & Mid(Format(CDbl(Rnd), "0." & String(Virgule - 15, "0")), 3)
      End If
    End If
    dico(x & y) = ""
  Wend
  plage = Application.Transpose(dico.keys)
End Sub
Fichier (3).

A+
 

Pièces jointes

  • Limite Listes Nb Aléatoires(3).xlsm
    75.6 KB · Affichages: 36
Dernière édition:

Magic_Doctor

XLDnaute Barbatruc
Re : Générer une liste de nombres réels aléatoires au moyen d'un dictionnaire

Merci à tous pour votre collaboration.
On peut dire que le problème est maintenant réglé.
30 décimales après la virgule... Fichtre !
Mais, une question, pour la culture : à quoi, ou dans quels domaines, sert une telle précision ?
Prenons, par exemple ("pratique") des masses ou des volumes. Les balances dont la précision va jusqu'au mg sont déjà chères. Quant aux volumes, les micropipettes de labo (très chères) ne vont guère au-delà du 1/1.000 de mL.
Une chose est certaine, en médecine cela ne sert à rien !
Peut-être qu'en physique quantique ou en cryptologie paranoïde, ou en météorologie utopique...

Excellente fin de journée à tous.
 

Magic_Doctor

XLDnaute Barbatruc
Re : Générer une liste de nombres réels aléatoires au moyen d'un dictionnaire

Tu as tout à fait raison. Raison pour laquelle ce genre d'execice devrait être obligatoire pour éviter chez certains quelques bévues...
 

Pièces jointes

  • Alzheimer.jpg
    Alzheimer.jpg
    50.3 KB · Affichages: 52

Magic_Doctor

XLDnaute Barbatruc
Re : Générer une liste de nombres réels aléatoires au moyen d'un dictionnaire

Bonsoir,

Je reviens sur ce post au sujet d'une amélioration finale.
J'utilise la solution de job (post #23). Ça marche très bien. La macro dresse, dans une plage, une liste de nombres aléatoires définis entre 2 limites ou extrêmes. Ces limites sont incluses dans le choix aléatoire.
La sentence qui permet de choisir des nombres aléatoires est (si je ne me trompe pas...) :
VB:
x = Int((LimSup - LimInf) * Rnd + LimInf)
Dans le paramétrage de la macro, je voudrais rajouter 2 précisions supplémentaires, à savoir si les limites sont incluses ou pas, par exemple :
VB:
Sub Aleatoire(LimInf As Double, crochet1 as string, LimSup As Double, crochet2 as string, plage As Range, Virgule As Byte)
Les "crochets" étant "[" ou "]" (et pas autre chose), de telle sorte que :
VB:
Sub Aleatoire(LimInf As Double, "[", LimSup As Double, "]", plage As Range, Virgule As Byte)
--> les 2 limites sont incluses
VB:
Sub Aleatoire(LimInf As Double, "[", LimSup As Double, "[", plage As Range, Virgule As Byte)
--> seule la limite inférieure est incluse
VB:
Sub Aleatoire(LimInf As Double, "]", LimSup As Double, "]", plage As Range, Virgule As Byte)
--> seule la limite supérieure est incluse
VB:
Sub Aleatoire(LimInf As Double, "]", LimSup As Double, "[", plage As Range, Virgule As Byte)
--> les 2 limites sont exclues

Comment s'y prendre ?

Merci d'avance pour tout conseil.
 
Dernière édition:

job75

XLDnaute Barbatruc
Re : Générer une liste de nombres réels aléatoires au moyen d'un dictionnaire

Bonjour Magic-Doctor,

x c'est la partie entière du nombre aléatoire, j'espère que c'est ce nombre que tu veux traiter...

Dans ce cas il vaut mieux déclarer LimInf et LimSup As Long :

Code:
Sub Aleatoire(LimInf&, crochet1$, LimSup&, crochet2$, plage As Range, Virgule As Byte)
  Dim NbLgn As Long, dico As Object, x$, y$
  
  If crochet1 <> "[" And crochet1 <> "]" Or crochet2 <> "[" And crochet2 <> "]" Then End
  If crochet1 = "]" Then LimInf = LimInf + 1
  If crochet2 = "]" Then LimSup = LimSup + 1
'-----
Je n'irai pas plus loin dans ce problème capillotracté.

A+
 
Dernière édition:

Magic_Doctor

XLDnaute Barbatruc
Re : Générer une liste de nombres réels aléatoires au moyen d'un dictionnaire

Bonsoir job,

Merci pour tes indices.
Je comprends que ce soit un peu exagéré, mais c'était essentiellement pour le fun, en prévision d'un USF qui va certainement me prendre la tête. Mais comme tu le disais "c'est bon contre l'allemand".

Peut-être que j'ai réglé le problème :

VB:
Sub Aleatoire(LimInf As Long, Crochet1 As String, LimSup As Long, Crochet2 As String, virgule As Byte, Plage As Range)
'Dresse une liste de nombres aléatoires compris entre 2 limites établies
'- LimInf : la plus petite valeur possible de la fourchette de nombres possibles
'- Crochet1 : si "[" --> LimInf est inclue
'             si "]" --> LimInf est exclue
'- LimSup : la plus grande valeur possible de la fourchette de nombres possibles
'- Crochet2 : si "]" --> LimSup est inclue
'             si "[" --> LimSup est exclue
'- Virgule : si = 0 --> nombres entiers
'            si > 0 --> détermine alors le nombre de décimales après la virgule (max : 30)
'- Plage : plage où apparaissent les nombres aléatoires
'job75 / Magic_Doctor

  Dim NbLgn As Long, dico As Object, X$, Y$
  
  If Crochet1 <> "[" And Crochet1 <> "]" Or Crochet2 <> "[" And Crochet2 <> "]" Then End
  If Crochet1 = "]" Then LimInf = LimInf + 1 / 10 ^ virgule
  If Crochet2 = "[" Then LimSup = LimSup - 1 / 10 ^ virgule
    
  NbLgn = Plage.Rows.Count 'nombre de lignes de la plage [Plage]
  If (LimSup - LimInf) * 10 ^ virgule < NbLgn Then End
  Set dico = CreateObject("Scripting.Dictionary")
  
  Randomize
  While dico.Count < NbLgn
    X = Int((LimSup - LimInf) * Rnd + LimInf)
    Y = ""
    If virgule Then
      If virgule < 16 Then
        Y = Mid(Format(CDbl(Rnd), "0." & String(virgule, "0")), 2)
      Else
        Y = Mid(Format(CDbl(Rnd), "0." & String(15, "0")), 2)
        Y = Y & Mid(Format(CDbl(Rnd), "0." & String(virgule - 15, "0")), 3)
      End If
    End If
    dico(X & Y) = ""
  Wend
  Plage = Application.Transpose(dico.keys)
End Sub
Bonne fin de soirée.
 

job75

XLDnaute Barbatruc
Re : Générer une liste de nombres réels aléatoires au moyen d'un dictionnaire

Re,

Pas d'accord pour ta redéfinition de LimSup :

If Crochet2 = "[" Then LimSup = LimSup - 1 / 10 ^ virgule
car cette valeur n'est jamais atteinte avec la manière dont x est défini.

Tu as mal testé, prends donc le code que j'ai donné.

A+
 

Membres actuellement en ligne

Aucun membre en ligne actuellement.

Statistiques des forums

Discussions
315 097
Messages
2 116 186
Membres
112 679
dernier inscrit
Yupanki