IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Caml Discussion :

Nombre aléatoire à partir d'un argument entier


Sujet :

Caml

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 14
    Points : 6
    Points
    6
    Par défaut Nombre aléatoire à partir d'un argument entier
    Bonjour à tous,

    j'aimerais créer une fonction qui me génère un nombre aléatoire en fonction d'un entier.

    Cette fonction doit tout le temps me retourner le même nombre pour l'entier passé en paramètre, mais bien sur un nombre différents pour un autre entier.

    J'en ai besoin pour générer un bruit, en fonction d'une position x, que j'utilise pour générer un bruit de Perlin.

    Voici le code C de la fonction que j'aimerais réalisé :

    double bruit(int x) {
    x = (x << 13) ^ x;
    return (((x * (x * x * 15985 + 735971) + 675332129) ^ 0x7FFFAAFF) / pow(2,31)-1);
    }

    Mais j'ai vu qu'on ne pouvait pas faire de décalage de bit en ocaml, donc je ne voit pas comment faire une fonction semblable

    Merci d'avance pour vos réponses.

  2. #2
    Membre éprouvé
    Avatar de Cacophrene
    Homme Profil pro
    Biologiste
    Inscrit en
    Janvier 2009
    Messages
    535
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Biologiste

    Informations forums :
    Inscription : Janvier 2009
    Messages : 535
    Points : 1 125
    Points
    1 125
    Par défaut
    Bonjour !

    Citation Envoyé par moongui
    j'ai vu qu'on ne pouvait pas faire de décalage de bit en ocaml
    Je ne sais pas où tu l'as vu, mais c'est une erreur. OCaml permet de faire des décalages de bits (cf la documentation du module Pervasives). Voici une traduction rapide de ton code C :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    let bruit n =
      let m = n lsl 13 lxor n in
      let p = ((m * (m * m * 15985 + 735971) + 675332129) lxor 0x7FFFAAFF) in
      float p /. (float max_int)
    Attention : je n'ai pas cherché à tester... il y a peut-être des choses à changer... je pense notamment à 0x7FFFAAFF qui est trop grand, et à max_int qui n'est pas exactement ce que tu veux.

    Cordialement,
    Cacophrène

  3. #3
    Membre éprouvé
    Profil pro
    Inscrit en
    Avril 2007
    Messages
    832
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2007
    Messages : 832
    Points : 1 104
    Points
    1 104
    Par défaut
    J'ai fait une petite version utilisant Int32, au cas où le nombre de bits soit important :
    Code ocaml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    let bruit32 n =
      let module I = Int32 in
      let n = I.of_int n in
      let m = I.logxor (I.shift_left n 13) n in
      let ( *:), (+:) = I.mul, I.add in
      let p = I.logxor 0x7FFFAAFFl (m *: (m *: m *: 15985l +: 735971l) +: 675332129l) in
      I.to_float p /. (2. ** 31. -. 1.)

  4. #4
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 14
    Points : 6
    Points
    6
    Par défaut
    Citation Envoyé par Cacophrene Voir le message
    Bonjour !


    Je ne sais pas où tu l'as vu, mais c'est une erreur. OCaml permet de faire des décalages de bits (cf la documentation du module Pervasives). Voici une traduction rapide de ton code C :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    let bruit n =
      let m = n lsl 13 lxor n in
      let p = ((m * (m * m * 15985 + 735971) + 675332129) lxor 0x7FFFAAFF) in
      float p /. (float max_int)
    Attention : je n'ai pas cherché à tester... il y a peut-être des choses à changer... je pense notamment à 0x7FFFAAFF qui est trop grand, et à max_int qui n'est pas exactement ce que tu veux.

    Cordialement,
    Cacophrène
    Merci cacophéne pour ta réponse. Au sujet du fait que j'ai dit qu'ocaml ne faisait pas de décalage de bit, ca montre qu'on trouve tout est n'importe quoi sur le net


    Citation Envoyé par bluestorm Voir le message
    J'ai fait une petite version utilisant Int32, au cas où le nombre de bits soit important :
    Code ocaml : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    let bruit32 n =
      let module I = Int32 in
      let n = I.of_int n in
      let m = I.logxor (I.shift_left n 13) n in
      let ( *:), (+:) = I.mul, I.add in
      let p = I.logxor 0x7FFFAAFFl (m *: (m *: m *: 15985l +: 735971l) +: 675332129l) in
      I.to_float p /. (2. ** 31. -. 1.)
    Merci aussi a toit blustorm. Je vais me servir de ta version, car elle me retourne un float positif, alors que celle de cacophéne peut retourner un float negatif ou positif. Mais je ne critique pas, c'est très gentil à vous d'avoir répondu. Je vais tester ça .

    Bonne soirée et bon début de semaine !

  5. #5
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 14
    Points : 6
    Points
    6
    Par défaut
    rectification : la tienne aussi de version peut retourner un float négatif bluestorm. Exemple, pour bruit32 600, ça retourne float = -0.233280082341879635.

    Savez vous à quoi c'est du ?

  6. #6
    Membre habitué
    Profil pro
    Inscrit en
    Avril 2009
    Messages
    128
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Avril 2009
    Messages : 128
    Points : 146
    Points
    146
    Par défaut
    en C aussi on a une valeur négative pour 600

  7. #7
    Membre à l'essai
    Inscrit en
    Octobre 2009
    Messages
    14
    Détails du profil
    Informations forums :
    Inscription : Octobre 2009
    Messages : 14
    Points : 10
    Points
    10
    Par défaut
    je ne sais pas du tout de quoi parle le code mais le nombre négatif n'est pas du a un dépassement de capacité ?

  8. #8
    Membre éprouvé
    Avatar de Cacophrene
    Homme Profil pro
    Biologiste
    Inscrit en
    Janvier 2009
    Messages
    535
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Biologiste

    Informations forums :
    Inscription : Janvier 2009
    Messages : 535
    Points : 1 125
    Points
    1 125
    Par défaut
    Bonjour !

    Citation Envoyé par Soshius
    je ne sais pas du tout de quoi parle le code mais le nombre négatif n'est pas du a un dépassement de capacité ?
    Si c'est exactement ça. Le problème vient du fait qu'on doit d'abord manipuler des entiers pour faire les décalages de bits, plutôt que de passer directement aux flottants. Donc pour n = 600, on a m = 4915213 soit un peu moins que 5.10⁶. Il est alors facile de se rendre compte que le produit m * m doit être de l'ordre de 2,5.10¹³, ce qui correspond grosso modo à 2⁴⁴. Bien entendu, en C comme en OCaml ou dans tout autre langage de programmation, les entiers codés sur 32 bits ne permettent pas de représenter ce nombre.

    Quelques suggestions :

    • Réécrire le code de bluestorm avec le module Int64.
    • Prendre la valeur absolue du résultat (certes pas très élégant).
    • Restreindre les valeurs de n données en entrée, si c'est possible.
    • Chercher une autre formule pour générer du bruit.

    Toutes ces suggestions ont leurs avantages et leurs inconvénients. Je ne sais pas si l'une d'entre elles est préférable aux autres. Quelles sont les contraintes les plus importantes sur ce code (performances, valeur unique pour un n donné...) ?

    Cordialement,
    Cacophrène

  9. #9
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 14
    Points : 6
    Points
    6
    Par défaut
    Il n'y a pas vraiment de contraintes sur ce code, mise à par le fait que pour l'entier x passé en paramètre, la valeur doit être la même à chaque appel de cette fonction pour x. La valeur retournée doit aussi être comprise entre 0 et 1, en float. Bien sur, pour une autre valeur de x, la valeur retournée doit être différente.

    J'ai besoin de cette fonction pour générer un bruit de perlin, afin de modéliser des textures réalistes pseudo-aléatoires.

    J'ai fait le tour de la fonction.

    Pour passer le code de bluestorm en Int64, je dois juste faire
    let module I = Int64 in non ?

    Encore merci pour votre aide

  10. #10
    Membre éprouvé
    Avatar de Cacophrene
    Homme Profil pro
    Biologiste
    Inscrit en
    Janvier 2009
    Messages
    535
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Biologiste

    Informations forums :
    Inscription : Janvier 2009
    Messages : 535
    Points : 1 125
    Points
    1 125
    Par défaut
    Bonjour !

    Citation Envoyé par moongui
    Pour passer le code de bluestorm en Int64, je dois juste faire let module I = Int64 in non ?
    Il faut aussi remplacer le suffixe l par L pour les nombres. Par exemple 15985l devient 15985L.

    Cordialement,
    Cacophrène

  11. #11
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 14
    Points : 6
    Points
    6
    Par défaut
    Rebonsoir,

    j'ai retranscris la fonction en version Int64, mais c'est pire . Mon code :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
     
    let bruit64 n =
      let module I = Int64 in
      let n = I.of_int n in
      let m = I.logxor (I.shift_left n 13) n in
      let ( *:), (+:) = I.mul, I.add in
      let p = I.logxor 0x7FFFAAFFL (m *: (m *: m *: 15985L +: 735971L) +: 675332129L) in
      I.to_float p /. (2. ** 31. -. 1.);;
    bruit64 600 retourne :float = -391264300.41547668

    alors que bruit32 600 retourne : float = -0.233280082341879635

    Je suis débutant, peut-être ai-je du mal modifier la fonction

    Cordialement,
    moongui

  12. #12
    Membre éprouvé
    Avatar de Cacophrene
    Homme Profil pro
    Biologiste
    Inscrit en
    Janvier 2009
    Messages
    535
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Biologiste

    Informations forums :
    Inscription : Janvier 2009
    Messages : 535
    Points : 1 125
    Points
    1 125
    Par défaut
    Re,

    Dans ce cas il y a toujours un débordement. Ça doit venir du fait que, dans mon précédent message, je me suis arrêté dès que j'ai trouvé une valeur supérieure à 2³². Mais en fait, l'entier que l'on obtient pour n = 600 avant le dernier logxor (celui avec 0x7FFFAAFFL) est supérieur à 2⁶⁴...

    Cordialement,
    Cacophrène

  13. #13
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 14
    Points : 6
    Points
    6
    Par défaut
    Bonjour,

    en effet, ça semble logique.

    Me voila donc coincer .

    J'ai pensé créer un tableau, ou je mettais mes valeurs aléatoire à l'avance, et puis par exemple bruit 20 reviendrais à chercher la valeur du tableau à l'indice 20.

    Mais en fait, c'est compliqué dans le sens ou je peut avoir de très très grand tableau car dans l'utilisation de programme, je peut faire appelle par exemple à bruit (x*pow(2,8)).....

    Si quelqu'un à une idée, je sèche .....

    Merci


    Moongui

  14. #14
    Membre éprouvé
    Avatar de Cacophrene
    Homme Profil pro
    Biologiste
    Inscrit en
    Janvier 2009
    Messages
    535
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Royaume-Uni

    Informations professionnelles :
    Activité : Biologiste

    Informations forums :
    Inscription : Janvier 2009
    Messages : 535
    Points : 1 125
    Points
    1 125
    Par défaut
    Bonjour !

    Citation Envoyé par moongui
    J'ai pensé créer un tableau, ou je mettais mes valeurs aléatoire à l'avance, et puis par exemple bruit 20 reviendrais à chercher la valeur du tableau à l'indice 20.
    C'est une solution affreusement gourmande en mémoire, comme tu l'as remarqué... Il ne faut pas utiliser un tableau pour ça, mais une table de hachage. Cette table reçoit n comme clef et le résultat de bruit n comme valeur associée. De cette façon il n'y a pas de gaspillage de mémoire si tu veux n = 20 et puis n = 600.

    Documentation du module Hashtbl

    Cordialement,
    Cacophrène

  15. #15
    Futur Membre du Club
    Profil pro
    Inscrit en
    Décembre 2009
    Messages
    14
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Décembre 2009
    Messages : 14
    Points : 6
    Points
    6
    Par défaut
    Ok, je vais tester ca. Merci !

Discussions similaires

  1. [AC-2003] Réaliser un nombre aléatoire entier
    Par ronibalbo dans le forum VBA Access
    Réponses: 1
    Dernier message: 04/01/2011, 11h15
  2. Réponses: 4
    Dernier message: 28/04/2010, 14h13
  3. Obtenir un nombre aléatoire à partir d'un nombre référence ?
    Par supergrey dans le forum Mathématiques
    Réponses: 10
    Dernier message: 08/11/2008, 18h47
  4. Réponses: 3
    Dernier message: 08/03/2008, 11h01
  5. Nombre aléatoire dans un intervalle (à partir d'un autre compris [0,1) )
    Par zoonel dans le forum Algorithmes et structures de données
    Réponses: 10
    Dernier message: 16/01/2008, 14h00

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo