Aleatório sem base de tempo [fechado]


9

Os computadores não criam números aleatórios sem base, pois provavelmente o tempo é a base universal da aleatoriedade.

Quero que você crie um código que crie números aleatórios com estas regras:

  • Não é permitido que o tempo seja a base, em qualquer ponto do programa.
  • Funções aleatórias / pseudo-aleatórias predefinidas não são permitidas.
  • Os números gerados podem estar em qualquer intervalo. Bem, pelo menos, dois inteiros diferentes: D
  • Os números são repetidos.

2
Não está claro o que você quer dizer com "Os números gerados podem estar em qualquer intervalo". Você quer dizer que o codificador pode escolher um intervalo? Ou que eles devem suportar qualquer intervalo solicitado pelo usuário? Ambos são problemáticos. Se o usuário solicitar um intervalo, e se ele solicitar números fora dos limites dos tipos de dados internos? E se o codificador é livre para escolher, eu escolho inteiros entre 1 e 1.: D
Jonathan Van Matre

2
Deveria ter sido um código de golf ...
Mukul Kumar

Comecei esta pergunta como questão de popularidade, o código-golfe seria mais adequado para isso?
Dadan 03/03

@ Daniel Sim, mas deixar esta questão ser popularidade perguntas e postar uma nova pergunta com o golfe código com novas regras (na geração aleatória) que vai ser divertido
Mukul Kumar

11
usar a internet como uma semente parece trapaça, não é?
Dean MacGregor

Respostas:


6

Javascript

Foi divertido!

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())

Eu escrevi o Mersenne Twister em JS. Então, percebi que tinha que obter uma semente de algum lugar.

Então, eu decidi que iria obtê-lo a partir da API Stack Exchange! (Eu poderia usar localStoragee incrementar um contador, mas isso não é divertido.) Então, peguei as 10 respostas ativas mais recentes e depois peguei a cada 4 ou menos dígitos consecutivos na resposta e os adicionei.

Essas sementes são sempre diferentes, pois o Stack Overflow é atualizado constantemente (e minha cota continua diminuindo!) Os números incluem IDs de resposta, IDs de perguntas, pontuações, contagens de up / downvote, representantes / IDs de proprietários e os dados do wrapper (cota e tal ) Em uma corrida eu consegui 256845, então 270495, e então 256048, etc ....

Isso registra 10 números aleatórios de complemento de dois bits de 32 bits no console. Saída de amostra:

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());
        }
    }

}

A magia está no public NoTimeRandom(). Matrizes convertidas em strings podem confundir novos programadores, pois os números são aleatórios. Amostra (para char[]: [C@4a8e91eb). O nextmétodo é copiado de java.util.Random.

Saída de amostra:

134277366
467041052
-555611140
-1741034686
1420784423

Vamos testar a eficácia deste rng:

Na minha resposta a Approximate a Bell Curve , a geração de dados que usei depende de um bom rng. Vamos executá-lo com isso como o rng. Resultado:

insira a descrição da imagem aqui

Assim como eu pensava. Este é um rng bastante ruim.


5

C

Compile com o sinalizador -pthread (ou o que seu compilador usa).

#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;
}

Não tenho certeza se isso se qualifica ou não com base no padrão "tempo não é permitido", porque basicamente está usando o agendador como fonte de entropia, ignorando intencionalmente a segurança do encadeamento. Ele funciona usando uma função psuedo-aleatória bastante básica ( gerador de números aleatórios de Lehmer ) com uma semente inicial codificada. Em seguida, ele inicia 20 threads que executam o cálculo de Lehmer com um conjunto compartilhado de variáveis.

Parece funcionar bastante bem, eis algumas execuções consecutivas:

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: Pensei um pouco mais e percebi que isso não é baseado em tempo. Mesmo com um planejador completamente determinístico, a entropia não vem dos intervalos de tempo - vem do carregamento de todos os processos em execução no sistema.

EDIT 2 Depois de me inspirar no @Quincunx postando uma curva em sino, coloquei 12MB de aleatoriedade em um arquivo e enviei -o para o CAcert . Ele falhou em todos os testes obstinados, mas obteve um respeitável 7.999573 de 8 no teste ENT (apenas potencialmente determinístico). Curiosamente, dobrar a contagem de threads piorou.


4

C

Ele gera um número aleatório no intervalo de 0 a 255, usando a semente de https://stackoverflow.com/questions usando 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);
}

Exemplo de execução:

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;
}  

resultado

quaisquer 5 números aleatórios

três amostras
insira a descrição da imagem aqui

insira a descrição da imagem aqui

insira a descrição da imagem aqui


11
1º, 2º e 5º são muito próximos, mesmo padrão repetido nos 3 exemplos. não exatamente a saída esperada de um gerador de números aleatórios.
Izabera 3/03

@izabera Quando se trata de indicadores na geração de números aleatórios ... tudo depende do seu computador (a RAM e o processador) talvez o endereço alimentado por 'new int' no 'ptr' esteja sendo usado atualmente! Você tentou executar este código?
22614 Mukul Kumar

Deixe-me acrescentar uma pequena mudança
Mukul Kumar

Eu tentei agora, na minha máquina parece que sempre recebo coisas 11230576, 0, 11206992, 0, 2053725299que ainda não me parecem aleatórias.
Izabera 3/03

verifique em ideone
izabera 03/03

2

perl

O que é todo esse lixo com a obtenção de sementes pela internet? Parece trapaça para mim ;-) Prefiro dar minha semente a uma função hash criptográfica e fornecer saída no intervalo de 0 a 2 ^ 160-1 da seguinte forma:

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'

Sempre que você tem entropia de qualidade incerta, uma maneira de distribuí-lo com mais regularidade (mas não aumenta sua qualidade!) É canalizá-lo para tipos como SHA1 ou MD5, como fiz aqui. Para sementes pré-hash, usei pid e o endereço de uma referência aleatória. É claro que você poderia adicionar outras entradas para obter mais entropia, por exemplo, no x86, você pode usar o TSC - (mas inserir código de montagem em perl é um pouco difícil, então eu pulei).

Se você quiser ter uma saída diferente da do cara no próximo computador, basta ajustar "some_salt" para ser uma string do seu agrado. Ou deixe de fora se você é um minimalista =)


Eu acho que qualquer função criptográfica que vale o nome em uma biblioteca padrão usa um RNG criptograficamente seguro internamente.
duci9y

Não tenho certeza sobre isso. Digest :: MD5 / Digest :: SHA1 produz saída totalmente determinística e reproduzível, então para que ele precisa de um número aleatório?
precisa saber é o seguinte

Desculpa! Acabei de falar sobre sua resposta e pensei que você estava gerando uma chave em vez de um resumo.
duci9y

2

Java

Minha solução abusa do hashCode()método 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());
        }
    }
}

Saída de amostra:

31859448
22101035
11593610
4580332
25736626
32157998
3804398
32440180
19905449
2772678

Motivado por outras respostas que demonstram a aleatoriedade da solução, mudei minha solução para retornar os 16 bits do meio intretornados por 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();
    }
}

Gerei um arquivo de 19 MB (consistindo em 10 7 short ) e o enviei ao CACert . Aqui está a captura de tela do resultado (ele foi editado para ficar bonito, mas os números são deixados como estão):

Resultado

Fiquei surpreso com o resultado, pois ele registra 7.999991 no teste de entropia e passou (?) Em todos os 7 testes de Diehard.


2

Javascript
Gerando aleatório com o movimento do mouse do usuário

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)};

Últimos cinco dados copiados:
9637090187003
7828470680762
6045869361238
4220720695015
2422653391073


1

Bash, intervalo: ints entre 0 e 1

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

Então você quer dizer que escolhe apenas 0 ou 1?

Sim. Deverá cumprir "Os números gerados podem estar em qualquer intervalo. Bem, pelo menos, dois inteiros diferentes: D", não deveria?
Keba

Eu acho. Você acha que poderia expandi-lo para uma faixa maior?

echo -n & echo $!vai fazer, mas ser um RNG muito ruim. Você também pode alterar 2 com qualquer outro número, mas quanto maior o número, pior fica a "aleatoriedade".
Keba

Eu vejo. Obrigada pelo esclarecimento.

1

Rubi

Infelizmente, apenas para Mac. Usamos soxpara extrair bytes do microfone (como uma corda, ahem ...), invertê-lo para obter o cabeçalho de status no final (* tosse *), cortá-lo, cortá-lo, tirar o MD5 dos pedaços , abandone os caracteres não numéricos do hash, adicione os inteiros largish restantes, cole um 0.na frente, converta em um flutuador, pronto.

Gera flutuadores de comprimento variável no intervalo 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

Gerando aleatoriamente usando o ID do processo.

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

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

Saída de amostra:

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


0

Pitão

A concisão de Python nunca deixa de surpreender. Como usar a imagem aleatória de imgur aparentemente não é válida, usei uma grande fonte de aleatoriedade: o bate-papo 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 ensaios:

3258789746
1899058937
3811869909
274739242
1292809118

Não é verdadeiramente aleatório, mas, novamente, nenhuma delas é.


eu acho que a regra 2 não permite urls comowhatever.com/random
izabera

@izabera 2 das outras respostas o usaram?
QWR

não, você está usando explicitamente conteúdo gerado aleatoriamente. as outras respostas acessam apenas uma página da web não aleatória para obter uma semente e imprimir um número aleatório.
Izabera 3/03

@izabera Eu mudei minha fonte aleatória. O que você acha disso agora?
precisa saber é o seguinte

agora está tudo bem: D
izabera

0

perl

Eu vi muitas respostas que fizeram solicitações HTTP, o que parece um desperdício para mim, porque, sob as cobertas, há números aleatórios sendo transmitidos pela rede. Então, decidi escrever um código para passar um em um nível mais baixo:

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

Dá portas aleatórias no intervalo 0..65535, teoricamente. Na prática, existem várias portas que você nunca verá, portanto a distribuição está longe de ser perfeita. Porém, é AFAICT a quantidade mínima de trabalho que você pode fazer para obter alguma entropia de um host remoto que tenha uma porta aberta.

PS - O tratamento de erros é deixado como um exercício para o leitor ;-)


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;
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.