begin process at 2010 02 09 06:15:13
  Trouver un code source :
 
dans
 
Accueil > 

Code

 > 

Maths

 > GÉNÉRATEUR DE NOMBRES PSEUDO-ALÉATOIRES

GÉNÉRATEUR DE NOMBRES PSEUDO-ALÉATOIRES


 Information sur la source

Note :
Aucune note
Catégorie :Maths Classé sous :aléatoire, nombre, générateur, hash, algorithme Niveau :Débutant Date de création :02/07/2009 Date de mise à jour :03/08/2009 12:07:05 Vu / téléchargé :2 873 / 183

Auteur : Bacterius

Ecrire un message privé
Commentaire sur cette source (37)
Ajouter un commentaire et/ou une note

 Description

Cliquez pour voir la capture en taille normale
Bonjour, voici un algorithme de génération de nombres pseudo-aléatoires, basé sur l'algorithme de chiffrement LEA (posté un peu plus tôt sur le site). L'algorithme est très simple, puisqu'il comporte 2 lignes, et implique un modulo (en dehors du hash). Je le compare dans l'exemple au générateur de Delphi, et mine de rien, il tient le coup ! Pour l'initialisation du générateur, on utilise le temps machine (rien de difficile) et l'adresse mémoire de la fonction "randomize" ;). Son principal intérêt réside en le fait qu'il utilise son propre hash pour générer des nombres aléatoires. Je vous laisse le découvrir, si vous avez des questions n'hésitez pas !


 Conclusion

Voilà, tous commentaires, conseils, critiques, remarques, etc ...

Cordialement, Bacterius !

PS : Codé sous Delphi 7 Personal Edition.

 Fichier Zip

Les Membres Club peuvent télécharger directement un fichier contenu dans le zip sans télécharger le zip en entier !

Télécharger le zip


 Historique

03 août 2009 12:07:05 :
// Changement de l'algorithme

 Sources du même auteur

Source avec Zip Source avec une capture UNITÉ DE SUPPORT VISTA
Source avec Zip Source avec une capture GESTION DES "CRASHS D'APPLICATION"
Source avec Zip Source avec une capture CONJECTURE DU CARRÉ DES FACTEURS
Source avec Zip Source avec une capture EFFET VITRE ET THUMBNAILS SOUS VISTA
Source avec Zip Source avec une capture UTILISER UNE DLL INCLUSE EN RESSOURCES

 Sources de la même categorie

Source avec Zip Source avec une capture CONVERTISSEUR D'UN NOMBRE DÉCIMAL EN BINAIRE ET HEXADECIMAL par ludokk
Source avec Zip Source avec une capture PREMIER OU PAS? par ludokk
Source avec Zip Source avec une capture CONJECTURE DU CARRÉ DES FACTEURS par Bacterius
Source avec Zip Source avec une capture ALGORITHME DE HASH LEA par Bacterius
Source avec Zip Source avec une capture STATUTILS - LES STATISTIQUES par Bacterius

 Sources en rapport avec celle ci

Source avec Zip Source avec une capture LEA EN MODE CHIFFREMENT (SEA) par Bacterius
Source avec Zip Source avec une capture ALGORITHME DE HASH LEA par Bacterius
Source avec Zip Source avec une capture MA PETITE COMBINE par cantador
Source avec Zip GÉNÉRATEUR DE MOT DE PASSE par oliverdev
Source avec Zip Source avec une capture GÉNÉRATEUR DE FICHIERS ALÉATOIRES : CLIENT DU SITE : HTTP://... par PoulpHunter

Commentaires et avis

Commentaire de Forman le 03/07/2009 11:21:40

L'idée est originale, mais quand tu le compares à celui de Delphi, tu compares en termes de vitesse, c'est bien ça?

Qu'en est-il des performances "statistiques"? As-tu fait des tests numériques (moyenne, écart-type, moments)? Si j'ai bien compris, tu utilises une sorte de relation de récurrence de ce type:
seed(n+1) = somme des octets du hash de seed(n) = F(seed(n))

Est-on certain que la fonction F (ici somme des octets du hash) n'a pas de point fixe? Ou même de cycles très courts? Si on imagine que F(123456)=332 et F(332)=123456 et si jamais la seed atteint la valeur 332 ça n'est plus vraiment un bon générateur...


Commentaire de Bacterius le 03/07/2009 11:30:19

Non je ne comparais pas en test de vitesse, car je pense que l'algo de Delphi n'est pas basé sur un hash, et est donc probablement plus rapide, cependant l'algo que je propose est assez rapide, et il y a moyen d'aller encore plus vite en générant 4 nombres à la fois (puisque le hash est composé de 128 bits = 4*32 bits = 4*cardinal).
Pour les tests numériques j'étais en train de réfléchir à comment les faire, voir si certains nombres sortaient plusieurs fois, etc ... (c'est ça non) ?
Mais attention ce n'est pas la somme des octets du hash, c'est la somme des entiers sur 32 bits du hash. Et il doit exister une boucle récurrente comme tu le montres, donc je pense changer en quelque chose de moins linéaire que l'addition, comme un xor couplé d'une opération logique ou deux.

Cordialement, Bacterius !

Commentaire de Bacterius le 03/07/2009 11:31:45

Je procède aux tests statistiques dans une autre application exemple.

Cordialement, Bacterius !

Commentaire de Forman le 03/07/2009 12:10:25

C'est justement toute la difficulté des PNRG: trouver un compromis entre période élevée et calcul rapide. Dans ton cas je doute qu'il soit facile de déterminer mathématiquement la période de la plus petite boucle (à moins de trouver un exemple évident de boucle courte).

Ceci dit, vu que tu génères des nombres sur 32 bits, tu peux toujours faire un prog qui essaie successivement toutes les graines (ça ne fait que quelques milliards) pour calculer la plus petite période, quitte à le faire tourner quelques heures...

Commentaire de Bacterius le 03/07/2009 12:14:48

Forman, les performances statistiques révèlent pour l'instant que Delphi et LEA-RNG sont semblables du point de vue de la moyenne, de la médiane (bonne répartition des valeurs), du minimum et du maximum.

Par exemple, sur un échantillon de 500 000 nombres :

----------- Delphi ------ LEA-RNG ------
Moyenne   249780.80      250791.29
Médiane   249797.00      251842.50
Minimum      16             10
Maximum    499986         499983
Etendue    499970         499973

Cordialement, Bacterius !

Commentaire de Bacterius le 03/07/2009 12:16:03

Je ne comprends pas "la plus petite boucle". Tous les appels à random coutent le même nombre d'opérations ?

Cordialement, Bacterius !

Commentaire de Forman le 03/07/2009 12:29:11

Je voulais dire "la plus courte période", c'est à dire la plus courte suite de nombres u(i) pour 1<=i<=n telle que

F(U(i))=U(i+1) et F(U(n))=U(1)

Si tu trouves une suite très courte c'est pas bon  :)

Pour info, celui de delphi aurait une période de 2^32 (donc maximale, voir http://www.delphifr.com/forum/sujet-PERIODE-GENERATEUR-ALEATOIRE-DELPHI_1113617.aspx)

Commentaire de Bacterius le 03/07/2009 12:32:13

Ah tu veux dire par exemple :

Graine : 13 => 45 => 23 => 54 => 91 => 13 (! on repart sur la même suite) ?

Cordialement, Bacterius !

Commentaire de Forman le 03/07/2009 12:40:30

Oui c'est ça

Commentaire de Bacterius le 03/07/2009 13:14:43

Pour combler à ça ne pourrait-on pas faire en sorte que la graine ne prenne plus comme valeur la somme des entiers 32 bits du hash, mais 1 des entiers du hash selon si la graine est paire, divisible par 3, etc ... ? C'est peut-être une bonne idée.

Cordialement, Bacterius !

Commentaire de Forman le 03/07/2009 13:51:43

Si tu fais disparaitre une boucle spécifique quelque part, rien ne te garantis que tu ne vas pas en créer une ailleurs...

Le mieux c'est peut-être de faire des tests (calculer la plus petite longueur de boucle) et si tu as de la chance tu auras peut-être une valeur élevée.

Commentaire de Bacterius le 03/07/2009 13:52:02

Forman, je viens de penser à un truc. Définissons une fonction de hash H qui à tout entier de 32 bits associe sa signature de 128 bits. Notons V la valeur du générateur.
1. On initialise, V est égal à quelque chose (temps machine).
2. On appelle random.
Pour des raisons de clarté, notons W la valeur de V avant qu'elle ne passe au hash.
On a alors V = H(W);
Et le nombre aléatoire R = V mod Intervalle;
3. On réappelle random.
On a alors H(W) = H(H(W));
Or il a été prouvé que le hash d'un hash est unique (puisque le premier hash est unique). Ainsi la période de n'importe-quel nombre est ... théoriquement infinie (enfin théoriquement puisque en pratique on se heurte au théorème des tiroirs qui dit que pour toute fonction qui associe à un ensemble A un ensemble B (et où la taille de A est supérieure à celle B), 2 éléments de A seront nécessairement associés au même élément de B).
Le problème se situe donc nécessairement au moment où l'on va tenter de condenser le hash (128 bits) dans la valeur (32 bits).

Cordialement, Bacterius !

Commentaire de Forman le 03/07/2009 14:47:22

Ca n'est pas suffisant. Par exemple, la fonction identité (F(x)=x) est elle aussi une bijection (l'image d'un nombre est unique puisque c'est lui-même :-) or si tu l'utilises sur ta graine tu obtiens une suite stationnaire (toujours la même valeur) qui est la pire fonction random qu'on puisse imaginer.

J'ai fait des essais avec la fonction que tu as postée en recherchant des boucles de longueur au plus 16 et j'ai trouvé plusieurs boucles de longueur 2 (j'ai fait varier la seed initiale entre 0 et un milliard et j'ai calculé les 8 permières valeurs):

Loop detected (Length = 2):
Seed(1)=1576860536
Seed(2)=1243888324

Loop detected (Length = 2):
Seed(1)=1460177290
Seed(2)=4272665070

Loop detected (Length = 2):
Seed(1)=357440169
Seed(2)=2637825466

Loop detected (Length = 2):
Seed(1)=1610603249
Seed(2)=1231174083

Loop detected (Length = 2):
Seed(1)=1190741914
Seed(2)=1231279339

Ca signifie que si jamais la graine atteint l'une de ces valeurs ton générateur va osciller entre les 2 valeurs.

Si tu veux tester voici le source qui recherche les boucles. Il faut 2 boutons sur une fiche, l'un "start" l'autre "stop" et un mémo pour l'affichage des résultats.

Pour chercher des boucles plus longues il faut augmenter la valeur de MAX_TAB.

--------------------------------------------------------------------------------
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, LEA_hash, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    Memo1: TMemo;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
  private
    { Private declarations }
  public
    { Public declarations }
    Started,Stopped:Boolean;
  end;

var
  Form1: TForm1;

implementation

const
  MAX_TAB=$F;

var
Seed: Longword;
Seed0: LongWord=0;
Tab:array[0..MAX_TAB] of Longword;

procedure randomize;
begin
Seed := GetTickCount; { On se base sur le temps machine }
end;

procedure Random;
Var
H: THash;
begin
H := Hash(Seed, 4);            { On récupère le hash de la valeur actuelle du générateur       }
Seed := H.A + H.B + H.C + H.D; { On attribue à la valeur actuelle la somme des entiers du hash }
end;


{$R *.dfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
var
  a,p:LongWord;
  b,c,d:Integer;
begin
  if Started then
    Exit;
  Stopped:=False;
  Started:=True;
  p:=$1000000 div ((MAX_TAB+1)*(MAX_TAB+2));
  a:=Seed0 mod p;
  try
    repeat
      Inc(a);
      if a=p then begin
        a:=0;
        Caption:=Format('Initial seed = %u',[Seed0]);
        Application.ProcessMessages;
        if Stopped then
          Break;
      end;
      Seed:=Seed0;
      Inc(Seed0);
      b:=1;
      Tab[0]:=Seed;
      repeat
        Random;
        c:=0;
        while (Tab[c]<Seed) and (c<b) do
          Inc(c);
        if Tab[c]=Seed then begin
          b:=0;
          repeat
            Tab[b]:=Seed;
            Random;
            Inc(b);
          until (Seed<>Tab[0]) and (b>1);
          Memo1.Lines.Add(Format('Loop detected (Length = %u):',[b]));
          for c:=0 to b-1 do
            Memo1.Lines.Add(Format('Seed(%u)=%u',[c+1,Tab[c]]));
          Memo1.Lines.Add('');
          Break;
        end;
        for d:=b downto c do
          Tab[d]:=Tab[d-1];
        Tab[c]:=Seed;
        Inc(b);
      until b>MAX_TAB;
    until Seed0=High(LongWord);
  finally
    Started:=False;
  end;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  Stopped:=True;
end;

procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);
begin
  Stopped:=True;
end;

end.

--------------------------------------------------------------------------------

Commentaire de Forman le 03/07/2009 15:11:17

oups une petite erreur dans mon code plus haut (il trouvait bien les boucles mais affichait toujours qu'elles avaient une longueur de 2). Voici la nouvelle procédure:

--------------------------------------------------------------------------------
procedure TForm1.Button1Click(Sender: TObject);
var
  a,p:LongWord;
  b,c,d:Integer;
begin
  if Started then
    Exit;
  Stopped:=False;
  Started:=True;
  try
    p:=$1000000 div ((MAX_TAB+1)*(MAX_TAB+2));
    a:=Seed0 mod p;
    repeat
      Inc(a);
      if a=p then begin
        a:=0;
        Caption:=Format('Initial seed = %u',[Seed0]);
        Application.ProcessMessages;
        if Stopped then
          Break;
      end;
      Seed:=Seed0;
      Inc(Seed0);
      b:=1;
      Tab[0]:=Seed;
      repeat
        Random;
        c:=0;
        while (Tab[c]<Seed) and (c<b) do
          Inc(c);
        if Tab[c]=Seed then begin
          b:=0;
          repeat
            Tab[b]:=Seed;
            Random;
            Inc(b);
          until (Seed=Tab[0]) and (b>1);
          Tab[b]:=Seed;
          Memo1.Lines.Add(Format('Loop detected (Length = %u):',[b]));
          for c:=0 to b do
            Memo1.Lines.Add(Format('Seed(%u)=%u',[c,Tab[c]]));
          Memo1.Lines.Add('');
          Break;
        end;
        for d:=b downto c do
          Tab[d]:=Tab[d-1];
        Tab[c]:=Seed;
        Inc(b);
      until b>MAX_TAB;
    until Seed0=High(LongWord);
  finally
    Started:=False;
  end;
end;
--------------------------------------------------------------------------------

Et quelques résultats:

Loop detected (Length = 11):
Seed(0)=1576860536
Seed(1)=1243888324
Seed(2)=133932042
Seed(3)=3917576848
Seed(4)=1486399104
Seed(5)=1549541129
Seed(6)=1460177290
Seed(7)=4272665070
Seed(8)=1426530670
Seed(9)=1949176323
Seed(10)=3781238255
Seed(11)=1576860536

Loop detected (Length = 10):
Seed(0)=357440169
Seed(1)=2637825466
Seed(2)=826517477
Seed(3)=1427081938
Seed(4)=1610603249
Seed(5)=1231174083
Seed(6)=3321287677
Seed(7)=252121279
Seed(8)=1190741914
Seed(9)=1231279339
Seed(10)=357440169

Loop detected (Length = 3):
Seed(0)=1108601366
Seed(1)=563960130
Seed(2)=2017111036
Seed(3)=1108601366


Commentaire de Bacterius le 03/07/2009 15:13:52

Effectivement, et il y en a sûrement beaucoup d'autres au-delà de seed = 1.000.000.000 ! Je comprends bien le principe, et ça prouve bien la faiblesse de l'addition. En effet, j'ai remplacé les additions par des ou-exclusifs pour voir, et rien n'est détecté jusqu'au milliard !
Seed := H.A xor H.B xor H.C xor H.D;
Maintenant l'important serait de voir si l'on peut obtenir des périodes de longueur supérieure à X (où X est la quantité de nombres aléatoires requis pour une tâche quelconque), je pense.

Cordialement, Bacterius !

Commentaire de Bacterius le 03/07/2009 15:33:43

Mais en fait si je comprends bien Forman, ton code va chercher toutes les graines pour lesquelles il y aura une répétition en moins de MAX_TAB nombres aléatoires ?

Cordialement, Bacterius !

Commentaire de Forman le 03/07/2009 15:39:33

Oui c'est ça.

Mais au-delà de 16 répétitions ça prend un temps monstrueux.

Le problème pour chercher les boucles c'est qu'il faut faire un compromis entre mémoire et vitesse. Il est possible d'aller un plus vite pour chercher une longue boucle en fixant une grande quantité de mémoire.

Commentaire de Forman le 03/07/2009 15:48:04

J'ai détecté une boucle de 8668 éléments avec le ou exclusif (elle commence à 305295269). Mais évidemment je n'ai pas fait de recherche exhaustive.

Effectivement si tu sais qu'une période de longueur N est acceptable alors si ton code fait au moins aussi bien c'est OK. Après il faut aussi regarder la répartition statistique des éléments des boucles (vérifier que c'est en gros uniforme dans l'intervalle).

Ce qui fait la difficulté de trouver des bons générateurs, c'est que pour une longueur de boucle minimale imposée, il doit aussi être très rapide à calculer. En ce sens les générateurs arithmétiques avec des modulo (comme celui de Borland) est un bon compromis...

Commentaire de Bacterius le 03/07/2009 15:51:47

Mais tout ceci peut-il indiquer une eventuelle faille dans l'algorithme de hashage lui-même ? Où c'est juste une particularité (les boucles) liée aux PRNG eux-mêmes ?

Cordialement, Bacterius !

Commentaire de Bacterius le 03/07/2009 15:53:15

En gros si pour un jeu j'ai besoin de générer 54 nombres aléatoires (jeu de carte) et que j'ai une chance "raisonnable" de tomber sur une période de 54 éléments au moins, le générateur est OK pour le jeu ?

Cordialement, Bacterius !

Commentaire de Forman le 03/07/2009 16:14:17

Je n'ai pas regardé l'algo de hash mais à mon avis ça n'a rien à voir.

Tout générateur déterministe (entendre par là dont le prochain état est codable un certains nombre de bits) est forcément périodique. Dans ton cas je peux t'affirmer sans faire aucun test qu'il y a au moins une boucle de longueur au plus 2^32 (soit 4 milliard environ :-) ... Tout simplement parce que ta graine est stockée sur 32 bits.

Dans ton exemple avec 54 cartes, effectivement un tel générateur serait raisonnablement efficace.

Mais je pense que dans ce cas, il faut précalculer une séquence: faire un tableau d'environ 54 entiers, stoker une séquence aléatoire dedans au lancement du programme (avec randomize avant) puis définir une nouvelle fonction random qui renvoie successivement tous les éléments du tableau en revenant au début quand la fin est atteinte.

Pourquoi? Tout simplement parce que ça prend moins de temps de renvoyer le n-ième élément d'un tableau que de calculer un hash, faire des xor, etc... pour un résultat "statistiquement équivalent".

Commentaire de Bacterius le 03/07/2009 16:21:28

Merci pour ces précisions Forman :)
Mais je ne comprends pas très bien l'avant-dernier paragraphe : si on reprend toujours le même tableau en le parcourant d'une façon linéaire, on tombera toujours sur la même séquence, et donc lors d'un nouveau tirage on aura exactement le même jeu ?

Cordialement, Bacterius !

Commentaire de Forman le 03/07/2009 16:45:01

Non, pas si tu fais un Randomize avant de remplir le tableau au lancement du jeu par exemple (lui-même étant basé sur l'horloge interne).

Commentaire de Bacterius le 03/07/2009 16:47:55

Oui mais si tu remplis ton tableau qu'une fois et que tu ne le renouvelles pas, il y aura les mêmes valeurs dedans ? Et donc le même tirage ... à moins que je ne comprennes pas ?

Cordialement, Bacterius !

Commentaire de Forman le 03/07/2009 16:55:40

Oui c'est bien ça. Mais si ta fonction Random entre dans une boucle d'une taille à peu près égale au bout d'un certain nombre d'utilisations, ça revient au même.

L'avantage c'est que lire un élément du tableau peut être plus rapide que de calculer un random avec un algo sophistiqué.

Commentaire de Bacterius le 29/07/2009 16:25:23

Après un peu moins d'un mois j'ai enfin (je crois) compris ton dernier commentaire. Tu voulais donc dire créer par exemple 30 tableaux de 54 éléments (qui représentent les 30 tirages possibles) au lancement du programme, puis choisir les tableaux l'un après l'autre pour faire un tirage, car il est improbable qu'un particulier fasse 30 parties à la suite sans fermer le jeu ... Non ?

Cordialement, Bacterius !

Commentaire de Forman le 29/07/2009 16:53:47

Oui c'est à peu près ça l'idée.

Mais on peut faire encore plus simple:
-déclarer un tableau TabRandom de 54*30=1620 éléments (ou plus!)
-dans la partie initialization, lancer FillArray:

procedure FillArray
var
  a:Integer;
begin
  for a:=Low(TabRandom) to High(TabRandom) do
  TabRandom[a]:=MyRandomFunction();
end;

-déclarer une variable RandomIndex de type Integer (initialisée à zéro).
-redéclarer la procédure randomize (par exemple en utilisant l'heure courante):

procedure Randomize();
begin
  RandomIndex:=Low(TabRandom)+((GetTickCount div 100) mod (High(TabRandom)-Low(TabRandom)+1));
end;

-redéclarer la fonction Random:

function Random: Integer;
begin
  Result:=TabRandom[RandomIndex];
  Inc(RandomIndex);
  if RandomIndex=High(TabRandom) then
    RandomIndex:=Low(TabIndex);
end;

Les valeurs de la fonction MyRandomFunction sont calculées une fois pour toute lors de l'initialisation, donc même si c'est une fonction compliquée qui prend du temps à s'exécuter ça ne ralentira pas le prog par la suite. C'est le même principe que les tables de Cosinus par exemple.

Il y a plusieurs intérêts d'utiliser quelque chose de semblable:
-on peut utiliser une fonction MyRandomFunction complexe avec un cahier des charges plus évolué que la fonction Random de base (par exemple, qui garantit qu'on ne tire jamais 2 fois de suite la même valeur, ou toute autre contrainte statistique) sans que ça rame par la suite
-il est possible de donner un ID à la partie: la première valeur prise par RandomIndex lors de l'utilisation de Randomize. Ainsi, on peut rejouer une partie avec la même suite du générateur aléatoire.

Il faut toutefois choisir une valeur assez élevée pour la taille du tableau TabRandom qui soit compatible avec le type d'application qu'on souhaite faire. Par exemple, si tu veux qu'il y ait en gros 30 parties possibles pour un jeu de carte alors effectivement 30*54 parait adapté. Pour une méthode de calcul de type Monte Carlo ça ne sera vraisemblablement pas assez et il faudrait augmenter la taille (typiquement à une valeur du même ordre que le nombre de tirages, tout en restant dans une utilisation raisonnable de la mémoire).

Commentaire de Bacterius le 29/07/2009 17:23:43

Je vois ... en gros on convertit du temps d'exécution (variable, en fonction du nombre d'appels à random) en espace mémoire (fixe, comme 30*54)) => bon plan.
Mais pour les méthodes de Monte-Carlo ça me paraît difficile à mettre en oeuvre, puisqu'il faut généralement plusieurs dizaines de milliards de nombres aléatoires pour obtenir un résultat probant.
Mais dans ce cas, on peut utiliser un fichier (généralement, on a plus d'espace disque que de mémoire). Je m'explique : au lancement du programme, on crée un fichier contenant, disons ... hmm ... cinq milliards (5.000.000.000) de nombres. Ca nous fait un fichier de 5.000.000.000 * 4 octets = 18 gigas. Bon ... c'est long à calculer mais on gagnera largement ce temps par la suite.
Ensuite, lors du calcul de Monte-Carlo, on va prendre les nombres par blocs de 128 mégas, soit 33554432 nombres, et faire notre calcul.
Et comme le calcul des 5 milliards de nombres est super long, on pourrait réutiliser ce fichier pour générer d'autres nombres, en appliquant une formule mathématique simple. Je m'explique encore : on génère nos 5 milliards de nombres, puis lorsqu'on utilise cet énorme fichier, on applique à chaque nombre du fichier la transformation suivante : Nombre + X (où X est une valeur unique au processus, typiquement GetTickCount).
Ca pourrait être intéressant comme source, ça ...

Cordialement, Bacterius !

Commentaire de Forman le 29/07/2009 18:04:38

Oui mais pour que ça vaille le coup il faut quand même que les nombres de la table générée "offline" soit utilisée plusieurs fois (sinon avec les accès disques on perdrait plus que ce qu'on a gagné). Ceci dit je crois qu'on peut télécharger des tables aléatoires sur le web.

Commentaire de Bacterius le 29/07/2009 18:18:14

Oui oui on réutilise la table générée ! Mais pour ne pas sortir les mêmes nombres, on utilise une petite formule mathématique : Nombre de la table + X + Y (X = GetTickCount au début du prog, Y = @Form1 ou un truc du genre). Car si par malheur on tombe sur la même valeur de X, les probabilités pour que l'on tombe en même temps sur un même Y sont limite inexistantes).
Et ... oui il existe des tables aléatoires sur le web, de plusieurs dizaines de gigaoctets (je crois en avoir vu une "soi-disant" de 1 téra dans une publicité).

Cordialement, Bacterius !

Commentaire de Bacterius le 03/08/2009 12:14:33

Bon, amélioration. Bon j'ai déjà changé l'algorithme de hash (il devient crucial dans cette version). Maintenant, la nouveauté c'est que :

Init seed => Seed = H(Seed) => Utilisation des 16 cardinals du hash => Seed = H(Seed) => ...

Ce qui fait que :
- la période minimale est de 16
- la période maximale peut atteindre 2^512 :o
- aucun risque de "boucles", l'algorithme est conçu pour ! Et comme l'initialisation se fait sur un nombre de 64 bits (et non plus 32) ... enfin voilà.

Cordialement, Bacterius !

Commentaire de Bacterius le 10/08/2009 14:58:38

Notons E l'état interne du générateur, et H la fonction de hashage qui à toute donnée associe 16 nombres uniques.

randomize : E = H(Int64(GetTickCount, @randomize)).

random : renvoie de façon itérative chacun des 16 nombres de E. Dès que l'on est à court de nombres, on effectue E = H(E). De cette façon, même si l'on tombe sur des suites qui se répètent, il faudrait pour rentrer dans un état de "boucle", avoir une suite de 16 nombres bien placés (c.a.d. où le premier nombre de la suite correspond au premier nombre de E). Qu'en penses-tu Forman ?

Cordialement, Bacterius !

Cordialement, Bacterius !

Commentaire de cmdmcmdm le 04/01/2010 22:54:57

J'ai un code d'alerte de l'antivirus au téléchargement ?

Possible ??

Commentaire de Bacterius le 04/01/2010 23:34:15

Y'a pas de raison normalement, il n'y a rien de méchant dans le code. Mais quelqu'un d'autre a déjà eu une difficulté avec une autre de mes sources, et ça s'était révélé une fausse alerte. De toute façon, tu peux dézipper sans exécuter aucun code, et tu peux regarder le code pour juger toi-même de sa dangerosité ... mais je n'ai pas voulu faire de truc malveillant donc ça doit être une fausse alerte.

Cordialement, Bacterius !

Commentaire de cmdmcmdm le 04/01/2010 23:38:50

C'est avec bullgard
A mon avis c'est une erreur de l'AV
A plus

Excuses

Commentaire de Forman le 05/01/2010 13:02:56

C'est déjà bien de pouvoir garantir une période minimale de longueur 16. Mais pas suffisant pour certains types de simulation (Monte Carlo). Tu pourrais aussi essayer de trouver un générateur arithmétique à congruences de période 2^64-1 (il faut quand même trouver les bons coefficients ceci dit). L'avantage c'est qu'ils sont redoutablement performants en terme de vitesse de calcul et donnent des résultats tout à fait acceptable dans la plupart des cas (hormis la cryptographie il me semble).

Commentaire de Bacterius le 05/01/2010 13:14:43

J'ai trouvé une idée intéressante, qui garantit une période maximale (du modulo donc) quelque soit la graine utilisée, à condition que le modulo soit un nombre premier. Ca semble donner des résultats très corrects pour les simulations et tout, mais bon pour la crypto, je ne peux rien garantir avec mes capacités actuelles. Davantage d'informations seront divulguées quand tous les documents seront finalisés :p

Cordialement, Bacterius !

 Ajouter un commentaire


Discussions en rapport avec ce code source dans le forum

Afficher un nombre aléatoire [ par Dagnir ] Salut, Bon voila mon but :Quand on clic sur mon bouton il y a un nombre (aléatoire) qui s'affiche dans un champ.Dans l'aide j'ai trouvé :function Rand Algorithme dans un tableau 2D [ par yopyop2003 ] Bonjour, Je souhaiterais calculer dans un tableau 2D, le nombre de minimal case separant 2 points, sachant que les deplacements horizontal, vertical Dessiner un nombre aléatoire de cercles [ par DeanCorso666 ] Salut,Je d&#233;bute en delphi. Je voulais creer aleatoirement un nombre de cercle &#224; l'aide de canvas.ellipse. Mon probl&#232;me c'est qu'il ne m exercice sur l'algorithme [ par kerfalla ] bonjour, je suis debutant dans la programmation et je suis colle sur les exercices suivants( voir ci dessous).je compte sur vos aides pour pouvoir con Algorithme de conversion BCD [ par racimo1985 ] Bonjour tt le monde, j besoin d'un algorithme qui montre le fonctionnement de  l'instruction DAA, cette instruction se base sur la conversion BCD du n Période du générateur aléatoire de Delphi [ par Adam_01 ] Bonjour,Est-ce que quelqu'un saurait quelle est la période et la dimension du générateur aléatoire utilisé par Delphi pour générer des nombres aléatoi Indy savoir le nombre de readln a faire ... [ par cyber37 ] Salut a tous,Je suis en train de refaire un programme en se moment mais je suis un peut embetter, je doit utiliser un socket BLOQUANT (obliger), j'ai demande d'aide [ par karima25 ] salut,j'ai un application à faire en langage Delphi, donc, j'ai besoin de connaitre la puissane k d'un nombre (nk) et la racine k d'un nombre.aidez mo Problème d'aléatoire [ par artmonchrie2 ] Bonjour à tous,Je crée un générateur de jeu de role et dans celui-ci je suis souvent amené à faire des jets de dé. Le jeu demandant différents types d


Nos sponsors


Appels d'offres

Sondage...

Comparez les prix

CalendriCode

Février 2010
LMMJVSD
1234567
891011121314
15161718192021
22232425262728

Consulter la suite du CalendriCode

 
Développement réalisé par Nicolas SOREL (Nix) avec l'aide de : Cyril DURAND et Emmanuel (EBArtSoft), Merci à Vincent pour ses précieux conseils.
CodeS-SourceS.com© Toute reproduction même partielle est interdite sauf accord écrit du Webmaster
CodeS-SourceS.com© est une marque déposée tous droits réservés

Google Coop CodeS-SourceS Google Coop CodeS-SourceS
Temps d'éxécution de la page : 1,310 sec (3)

Nous contacter | Annoncer sur CodeS-SourceS | Mentions légales