Aléatoire sans base de temps [fermé]


9

Les ordinateurs ne créent pas de nulle part des nombres aléatoires sans base, car le temps est très probablement la base universelle de l'aléatoire.

Je veux que vous créiez un code qui crée des nombres aléatoires avec ces règles:

  • Le temps n'est pas autorisé à être la base, à aucun moment du programme.
  • Les fonctions prédéfinies aléatoires / pseudo-aléatoires ne sont pas autorisées.
  • Les nombres générés peuvent être dans n'importe quelle plage. Eh bien au moins deux entiers différents: D
  • Les nombres sont repris.

2
On ne sait pas exactement ce que vous entendez par "les nombres générés peuvent être dans n'importe quelle plage". Voulez-vous dire que le codeur est libre de choisir une plage? Ou qu'ils doivent prendre en charge toute plage demandée par l'utilisateur? Ces deux problèmes sont problématiques. Si l'utilisateur demande une plage, que se passe-t-il s'il demande des nombres en dehors des limites des types de données intégrés? Et si le codeur est libre de choisir, je choisis des entiers entre 1 et 1.: D
Jonathan Van Matre

2
Devrait être un code-golf ...
Mukul Kumar

J'ai commencé cette question en tant que question de popularité, le code-golf serait-il mieux adapté à cela?
Dadan

@Daniel Ouais, mais que cette question soit une question de popularité et poste une nouvelle question avec le code golf avec de nouvelles règles (sur la génération aléatoire) qui seront amusantes
Mukul Kumar

1
utiliser Internet comme une graine semble tricher n'est-ce pas?
Dean MacGregor

Réponses:


6

Javascript

C'était amusant!

arr = []
index = 0

function init(seed) {
    index = 0
    arr[0] = seed
    for (var i = 1; i < 624; i ++) {
        arr[i] = (1812433253 * (arr[i-1] ^ (arr[i-1] >>> 30)) + i) | 0
    }
 }

function getNumber() {
    if (index == 0) generateNumbers()

    var y = arr[index]
    y ^= (y >>> 11)
    y ^= ((y << 7) & 2636928640)
    y ^= ((y << 15) & 4022730752)
    y ^= (y >>> 18)

    index = (index + 1) % 624
    return y
}

function generateNumbers() {
    for (var i = 0; i < 624; i ++) {
        var y = (arr[i] & 0x80000000) + (arr[(i+1) % 624] & 0x7fffffff)
        arr[i] = arr[(i + 397) % 624] ^ (y >>> 1)
        if (y % 2 != 0) arr[i] ^= 2567483615
    }
}

// let's get our seed now from the SE API
var x = new XMLHttpRequest()
x.open('GET', 'http://api.stackexchange.com/2.2/answers?pagesize=10&order=desc&sort=activity&site=stackoverflow&filter=!Sri2UzKb5mTfr.XgjE', false)
x.send(null)
// we've got the answer data, now just add up all the numbers.
// only 4 digits at a time to prevent too big of a number.
var seed = 0
var numbers = x.responseText.match(/\d{0,4}/g)
for (var i = 0; i < numbers.length; i++) seed += +numbers[i]

init(seed)
for (var i = 0; i < 10; i++) console.log(getNumber())

J'ai écrit le Mersenne Twister dans JS. Ensuite, j'ai réalisé que je devais obtenir une graine quelque part.

J'ai donc décidé de l'obtenir auprès de l'API Stack Exchange! (Je pouvais utiliser localStorageet incrémenter un compteur, mais ce n'est pas amusant.) Donc, j'ai saisi les 10 réponses actives les plus récentes, puis j'ai simplement pris tous les 4 chiffres consécutifs ou moins dans la réponse et les ai additionnés.

Ces graines sont toujours différentes, car Stack Overflow est constamment mis à jour (et mon quota continue de baisser!) Les chiffres incluent les ID de réponse, les ID de question, les scores, le nombre de votes positifs / négatifs, les rep / ID du propriétaire et les données d'encapsuleur (quota et autres) ). Sur un cours , je suis arrivé 256845, puis 270495, puis 256048, etc ....

Cela enregistre 10 nombres aléatoires de complément à deux de 32 bits dans la console. Exemple de sortie:

247701962
-601555287
1363363842
-1184801866
1761791937
-163544156
2021774189
2140443959
1764173996
-1176627822

5

Java

import java.util.Random;
import java.util.concurrent.atomic.AtomicLong;

/**
 *
 * @author Quincunx
 */
public class NoTimeRandom extends Random {

    private AtomicLong seed;

    public NoTimeRandom() {
        byte[] ba = (new String[0].toString() + new String[0].toString()
                + new String[0].toString() + new String[0].toString()
                + new String[0].toString() + new String[0].toString()).getBytes();
        int seed1 = 1;
        for (byte b : ba) {
            seed1 += b;
        }

        ba = (new String[0].toString() + new String[0].toString()
                + new String[0].toString() + new String[0].toString()
                + new String[0].toString() + new String[0].toString()).getBytes();
        long seed2 = 1;
        for (byte b : ba) {
            seed2 += b;
        }

        seed = new AtomicLong(seed1 ^ seed2);
    }

    @Override
    protected int next(int bits) {
        long oldseed, newseed;
        AtomicLong seed = this.seed;
        do {
            oldseed = seed.get();
            newseed = (oldseed * 25214903917L + 11) & 281474976710655L;
        } while (!seed.compareAndSet(oldseed, newseed));

        return (int) (newseed >>> (48 - bits));
    }

    public static void main(String[] args) {
        Random r = new NoTimeRandom();

        for (int i = 0; i < 5; i++) {
            System.out.println(r.nextInt());
        }
    }

}

La magie est dans le public NoTimeRandom(). Les tableaux convertis en chaînes peuvent dérouter les nouveaux programmeurs, car les nombres sont aléatoires. Échantillon (pour char[]:) [C@4a8e91eb. La nextméthode est copiée à partir de java.util.Random.

Exemple de sortie:

134277366
467041052
-555611140
-1741034686
1420784423

Testons l'efficacité de ce rng:

Dans ma réponse à Approximate a Bell Curve , la génération de données que j'ai utilisée dépend d'un bon rng. Exécutons-le avec ceci en tant que rng. Production:

entrez la description de l'image ici

Exactement ce que je pensais. Ceci est un rng assez moche.


5

C

Compilez avec l'indicateur -pthread (ou tout ce que votre compilateur utilise).

#include <stdio.h>
#include <pthread.h>

#define m (unsigned long)2147483647
#define q (unsigned long)127773
#define a (unsigned int)16807
#define r (unsigned int)2836 

static unsigned long seed;
pthread_t t[20];
int lo, hi, done;

void *pseudorandom(void *id)
{
    while(done)
    {
        int test;
        hi = seed/q;
        lo = seed%q;
        test = a * lo - r * hi;
        if (test > 0) seed = test;
        else seed = test + m;
    }
}

main()
{
     int i;
     seed = 54321;
     done = 1;

     for(i = 0; i < 20; i++) 
     {
          pthread_create(&(t[i]), NULL, &pseudorandom, NULL);
     }

     for (i = 0; i < 10; i++) 
     {
          printf("%lu\n", seed);
     }

     done = 0;
}

Je ne sais pas si cela se qualifie ou non en fonction de la norme "le temps n'est pas autorisé", car il utilise essentiellement le planificateur comme source d'entropie en ignorant intentionnellement la sécurité des threads. Il fonctionne en utilisant une fonction pseudo-aléatoire assez basique ( générateur de nombres aléatoires Lehmer ) avec une graine initiale codée en dur. Il démarre ensuite 20 threads qui exécutent tous le calcul de Lehmer avec un ensemble partagé de variables.

Semble assez bien fonctionner, voici quelques runs consécutifs:

comintern ~ $ ./a.out
821551271
198866223
670412515
4292256
561301260
1256197345
959764614
874838892
1375885882
1788849800
comintern ~ $ ./a.out
2067099631
953349057
1736873858
267798474
941322622
564797842
157852857
1263164394
399068484
2077423336

EDIT: A réfléchi un peu plus et a réalisé que ce n'est pas du tout basé sur le temps. Même avec un ordonnanceur complètement déterministe, l'entropie ne provient pas des tranches de temps - elle provient du chargement de tous les processus en cours d'exécution sur le système.

EDIT 2 Après m'être inspiré de @Quincunx qui a affiché une courbe en cloche, j'ai vidé 12 Mo d'aléatoire dans un fichier et l'ai téléchargé sur CAcert . Il a échoué à tous les tests purs et durs, mais a réussi un respectable 7,999573 sur 8 au test ORL (uniquement potentiellement déterministe). Curieusement, doubler le nombre de fils a aggravé la situation.


4

C

Il génère un nombre aléatoire dans la plage 0-255 en prenant la graine de https://stackoverflow.com/questions à l' aide wget.

#include <stdio.h>
main()
{
    FILE *file;
    unsigned char c,x;
    system("wget -O - https://stackoverflow.com/questions > quest.html");
    file = fopen ("quest.html", "r");
    while(c=fgetc(file) != EOF) x+=c;
    fclose(file);
    printf("%d",x);
}

Exemple d'exécution:

C:\Users\izabera>random
--2014-03-02 16:15:28--  https://stackoverflow.com/questions
Resolving stackoverflow.com... 198.252.206.140
Connecting to stackoverflow.com|198.252.206.140|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 85775 (84K) [text/html]
Saving to: `STDOUT'

100%[======================================>] 85,775      40.3K/s   in 2.1s

2014-03-02 16:15:31 (40.3 KB/s) - `-' saved [85775/85775]

15 /* <=================== THIS IS THE RANDOM NUMBER */
C:\Users\izabera>random
--2014-03-02 16:15:36--  https://stackoverflow.com/questions
Resolving stackoverflow.com... 198.252.206.140
Connecting to stackoverflow.com|198.252.206.140|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 85836 (84K) [text/html]
Saving to: `STDOUT'

100%[======================================>] 85,836      50.0K/s   in 1.7s

2014-03-02 16:15:38 (50.0 KB/s) - `-' saved [85836/85836]

76
C:\Users\izabera>random
--2014-03-02 16:15:56--  https://stackoverflow.com/questions
Resolving stackoverflow.com... 198.252.206.140
Connecting to stackoverflow.com|198.252.206.140|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 85244 (83K) [text/html]
Saving to: `STDOUT'

100%[======================================>] 85,244      36.0K/s   in 2.3s

2014-03-02 16:15:59 (36.0 KB/s) - `-' saved [85244/85244]

144

2

C ++

#include<iostream>
int main()
{
    int *ptr=new int,i=0;
    for(;i<5;i++)
    {
        std::cout<<*(ptr+i)<<'\n';
    }
    return 0;
}  

production

5 nombres aléatoires

trois échantillons
entrez la description de l'image ici

entrez la description de l'image ici

entrez la description de l'image ici


1
Les 1er, 2e et 5e sont assez proches, même schéma répété dans les 3 exemples. pas exactement la sortie attendue d'un générateur de nombres aléatoires.
izabera

@izabera Quand il s'agit de pointeurs pour générer des nombres aléatoires ... tout dépend de votre ordinateur (la RAM et le processeur) peut-être que l'adresse fournie par 'new int' dans 'ptr' est actuellement utilisée! Vous avez essayé d'exécuter ce code?
Mukul Kumar

Permettez-moi d'ajouter un petit changement
Mukul Kumar

je l'ai essayé maintenant, sur ma machine, il semble que j'obtienne toujours des choses comme 11230576, 0, 11206992, 0, 2053725299, ce qui ne me semble toujours pas aléatoire.
izabera

consultez-le à ideone
izabera

2

perl

Qu'est-ce que c'est que ces conneries avec obtenir des graines sur Internet? Cela ressemble à de la triche pour moi ;-) Je préfère donner ma graine à une fonction de hachage cryptographique à la place, et donner une sortie dans la plage 0 à 2 ^ 160-1 comme ceci:

use Digest::SHA1 qw(sha1);
use bigint;
sub r {
  $_ = \3;
  /^.*x([0-9a-f]+).$/;
  hex((unpack "H*", sha1 "some_salt".$1.$$)[0])
}
print join " ", r'

Chaque fois que vous avez une entropie de qualité incertaine, un moyen de la distribuer plus régulièrement (mais pas d'augmenter sa qualité!) Est de la diriger vers SHA1 ou MD5, comme je l'ai fait ici. Pour les graines de pré-hachage, j'ai utilisé pid et l'adresse d'une référence aléatoire. Vous pouvez bien sûr ajouter d'autres entrées pour plus d'entropie, par exemple sur x86, vous pouvez utiliser TSC - (mais l'inlining code d'assemblage en perl est un peu un ours, donc je l'ai ignoré).

Si vous voulez avoir une sortie différente de celle du gars sur le prochain ordinateur, ajustez simplement "some_salt" pour être une chaîne de votre goût. Ou laissez-le complètement si vous êtes minimaliste =)


Je suppose que toute fonction cryptographique digne de ce nom dans une bibliothèque standard utilise un RNG cryptographiquement sécurisé en interne.
duci9y

Je ne suis pas certain de ça. Digest :: MD5 / Digest :: SHA1 produisent une sortie entièrement déterministe et répétable, alors pourquoi a-t-il besoin d'un nombre aléatoire?
skibrianski

Désolé! Je viens de survoler votre réponse et j'ai pensé que vous génériez une clé au lieu d'un résumé.
duci9y

2

Java

Ma solution abuse de la hashCode()méthode de Objectclasse.

class G22640 {
    static class Rand {
        public int nextInt() {
            return new Object().hashCode();
        }
    }

    public static void main(String args[]) {
        Rand r = new Rand();
        for (int i = 0; i < 10; i++) {
            System.out.println(r.nextInt());
        }
    }
}

Exemple de sortie:

31859448
22101035
11593610
4580332
25736626
32157998
3804398
32440180
19905449
2772678

Motivé par d'autres réponses démontrant le caractère aléatoire de la solution, j'ai changé ma solution pour renvoyer les 16 bits du milieu du intretourné par Object.hashCode().

import java.io.*;

class G22640 {
    static class Rand {
        public short nextShort() {
            return (short) ((new Object().hashCode() >> 8) & 0xFFFF);
        }
    }

    public static void main(String args[]) throws IOException {
        Rand r = new Rand();

        for (int i = 0; i < 10; i++) {
            System.out.println(r.nextShort());
        }

        // generateToFile("random_22640.txt");
    }

    private static void generateToFile(String fileName) throws IOException {
        Rand r = new Rand();
        BufferedOutputStream o = new BufferedOutputStream(new FileOutputStream(fileName));

        for (int i = 0; i < 10000000; i++) {
            int a = r.nextShort();
            for (int j = 0; j < 2; j++) {
                o.write(a & 0xFF);
                a >>= 8;
            }
        }

        o.flush();
        o.close();
    }
}

J'ai généré un fichier de 19 Mo (composé de 10 7 short ) et je l' ai soumis à CACert . Voici la capture d'écran du résultat (il a été modifié pour être joli, mais les chiffres restent tels quels):

Résultat

J'ai été surpris du résultat, car il enregistre 7.999991 au test Entropy et réussit (?) Les 7 tests Diehard.


2

Javascript
Génération aléatoire avec le déplacement de la souris de l'utilisateur

var ranArr=[];
var random=0;
var first=second=0;
function generateR(event) {
ranArr.push(parseFloat(event.clientX+document.body.scrollLeft))
ranArr.push(parseFloat(event.clientY+document.body.scrollTop));
var len=ranArr.length;

for(var i=0;i<len;i++) {
    if(i<len/2) {

    first+=ranArr[i];
    } else {
    second += ranArr[i];
    }
}
third = second/first;
third = third+"";
console.log(third.substr(5));
}
document.onmousemove=function(event){generateR(event)};

Cinq dernières données copiées:
9637090187003
7828470680762
6045869361238
4220720695015
2422653391073


1

Bash, plage: entre 0 et 1

echo -n & echo "$! % 2" | bc

Vous voulez donc dire qu'il prend 0 ou 1 seulement?

Oui. Devrait remplir "Les nombres générés peuvent être dans n'importe quelle plage. Eh bien au moins deux entiers différents: D", n'est-ce pas?
Keba

Je suppose. Pensez-vous que vous pourriez l'étendre à une gamme plus large?

Ça echo -n & echo $!suffira, mais soyez un très mauvais RNG. Vous pouvez également changer 2 avec n'importe quel autre nombre, mais plus le nombre est grand, plus le "hasard" est mauvais.
Keba

Je vois. Merci pour l'explication.

1

Rubis

Malheureusement Mac uniquement. Nous utilisonssox pour extraire les octets du microphone (comme une chaîne, ahem ...), l'inverser pour obtenir l'en-tête d'état à la fin (* toux *), le couper, le couper, prendre le MD5 des morceaux , abandonnez les caractères non numériques du hachage, ajoutez les entiers les plus larges restants, collez un 0.sur le devant, convertissez-le en flottant, c'est fait.

Génère des flotteurs de longueur variable sur l'intervalle 0..1.

require 'open3'
require 'digest'

class InsecureRandom
  def self.random_number
    n = self.get_bytes
    .map! { |r| Digest::MD5.hexdigest(r) }
    .map! { |r| r.gsub(/[a-z]/, '') }
    .map!(&:to_i)
    .reduce(0,:+)

    "0.#{n}".to_f
  end

  private
  def self.get_bytes
    Open3.popen3('sox -d -q -e unsigned-integer -p') do |_, stdout, _|
      stdout.read(20000).reverse.split('\\').to_a.take(20)
    end
  end
end

randomish = Array.new(20) { InsecureRandom.random_number }
puts randomish
# >> 0.2333530765409607
# >> 0.17754047429753905
# >> 0.936039801228352
# >> 0.2781141892158962
# >> 0.6243140263525706
# >> 0.1583419168189452
# >> 0.2173713056635174
# >> 0.930577106355
# >> 0.11215268787922089
# >> 0.13292311877287152
# >> 0.14791818448435443
# >> 0.4864648362730452
# >> 0.5133193113765809
# >> 0.3076637743531015
# >> 0.16060112015793476
# >> 0.7294970251624926
# >> 0.18945368886946876
# >> 0.9970215825154781
# >> 0.13775531752383308
# >> 0.5794383903900283

1

C

Génération aléatoire à l'aide de l'ID de processus.

#include <unistd.h>
#include <stdio.h>

int     main(void)
{
    int out;
    out *= out *= out = getpid();
    printf("%d\n", out % 1024);
    return (0);
}

Exemple de sortie:

-767
0
769
-1008
337
-768
369
-752
-415
0
-863
784
-463
256
657


0

python

La concision de Python ne cesse d'étonner. Étant donné que l'utilisation de l'image aléatoire d'imgur n'est pas valide apparemment, j'ai utilisé une grande source d'aléatoire: le chat de stackoverflow!

   import urllib.request

def getrand():
    req = urllib.request.Request("http://chat.stackoverflow.com/")
    response = urllib.request.urlopen(req)
    the_page = str(response.read())

    x = 1
    for char in the_page:
        x = (3*x + ord(char) + 1)%2**32

    print(x)

5 essais:

3258789746
1899058937
3811869909
274739242
1292809118

Pas vraiment aléatoire, mais là encore, aucun de ces éléments ne l'est.


je pense que la règle 2 ne permet pas les URL commewhatever.com/random
izabera

@izabera 2 des autres réponses l'ont utilisé?
qwr

non, vous utilisez explicitement du contenu généré aléatoirement. les autres réponses accèdent simplement à une page Web non aléatoire pour obtenir une graine, puis imprimer un nombre aléatoire.
izabera

@izabera J'ai changé de source aléatoire. Qu'en pensez-vous maintenant?
qwr

maintenant ça va: D
izabera

0

perl

J'ai vu beaucoup de réponses qui ont fait des requêtes HTTP, ce qui me semble inutile parce que sous les couvertures il y a des nombres aléatoires qui sont transmis sur le fil. J'ai donc décidé d'écrire du code pour en glisser un à un niveau inférieur:

use IO::Socket::INET;
print ((sockaddr_in(getsockname(IO::Socket::INET->new(
    PeerAddr => "google.com", PeerPort => 80, Proto => "tcp"
))))[0]);

Donne des ports aléatoires dans la plage 0..65535, théoriquement. En pratique, il y a un certain nombre de ports que vous ne verrez jamais, donc la distribution est loin d'être parfaite. Mais c'est, AFAICT, la quantité minimale de travail que vous pouvez faire pour obtenir de l'entropie d'un hôte distant avec un port ouvert.

PS - La gestion des erreurs est laissée au lecteur comme exercice ;-)


0

C

// alternating two pure-RNG inspired by http://xkcd.com/221/
int getRandomNumber()
{
   static int dice_roll = 0;
   dice_roll++;
   if ((dice_roll % 2) == 1)
   {
      return 4;
   } 
   else
   {
      return 5;
   } 
}

int main(int argc, char **argv)
{
    printf("%d\n%d\n", getRandomNumber(), getRandomNumber())
    return 0;
}
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.