Acak tanpa Dasar Waktu [ditutup]

9

Komputer tidak keluar dari tempat membuat angka acak tanpa dasar, karena kemungkinan besar, waktu adalah dasar universal dari keacakan.

Saya ingin Anda membuat kode yang membuat angka acak dengan aturan ini:

  • Waktu tidak boleh menjadi dasar, pada titik mana pun dari program ini.
  • Fungsi acak / pseudo-acak yang telah ditentukan tidak diizinkan.
  • Angka yang dihasilkan dapat berada dalam kisaran apa pun. Setidaknya dua bilangan bulat yang berbeda: D
  • Angka digema.
Dadan
sumber
2
Tidak jelas apa yang Anda maksud dengan "Angka yang dihasilkan dapat berada dalam kisaran apa pun". Apakah maksud Anda pembuat kode bebas memilih rentang? Atau mereka harus mendukung rentang apa pun yang diminta pengguna? Keduanya bermasalah. Jika pengguna meminta rentang, bagaimana jika mereka meminta angka di luar batas tipe data bawaan? Dan jika pembuat kode bebas untuk memilih, saya memilih bilangan bulat antara 1 dan 1.: D
Jonathan Van Matre
2
Seharusnya kode-golf ...
Mukul Kumar
Saya memulai pertanyaan ini sebagai pertanyaan popularitas, apakah golf kode lebih cocok untuk ini?
Dadan
@Aniel Ya tapi biarkan pertanyaan ini menjadi popularitas-pertanyaan dan posting pertanyaan baru dengan kode golf dengan aturan baru (pada generasi acak) yang akan menyenangkan
Mukul Kumar
1
menggunakan internet sebagai benih sepertinya curang bukan?
Dean MacGregor

Jawaban:

6

JavaScript

Itu tadi menyenangkan!

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

Saya menulis Mersenne Twister di JS. Kemudian, saya menyadari bahwa saya harus mendapatkan benih dari suatu tempat.

Jadi, saya memutuskan untuk mendapatkannya dari Stack Exchange API! (Saya bisa menggunakan localStoragedan menambah penghitung, tapi itu tidak menyenangkan.) Jadi, saya mengambil 10 jawaban yang paling aktif, dan kemudian saya hanya mengambil setiap 4 atau kurang digit berturut-turut dalam respons dan menambahkannya.

Benih-benih ini selalu berbeda, karena Stack Overflow terus-menerus memperbarui (dan kuota saya terus turun!) Jumlahnya termasuk ID jawaban, ID pertanyaan, skor, jumlah naik / turun, rep pemilik / ID, dan data pembungkus (kuota dan semacamnya) ). Sekali jalan saya dapatkan 256845, lalu 270495, dan kemudian 256048, dll ....

Ini mencatat 10 angka komplemen acak 32-bit dua ke konsol. Output sampel:

247701962
-601555287
1363363842
-1184801866
1761791937
-163544156
2021774189
2140443959
1764173996
-1176627822
Gagang pintu
sumber
5

Jawa

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

}

Keajaiban ada di public NoTimeRandom(). Array yang dilemparkan ke string dapat membingungkan programmer baru, karena jumlahnya acak. Contoh (untuk char[]: [C@4a8e91eb). The nextMetode disalin dari java.util.Random.

Output sampel:

134277366
467041052
-555611140
-1741034686
1420784423

Mari kita menguji efektivitas rng ini:

Dalam jawaban saya untuk Approximate a Bell Curve , pembuatan data yang saya gunakan tergantung pada rng yang baik. Mari kita jalankan dengan ini sebagai rng. Keluaran:

masukkan deskripsi gambar di sini

Seperti yang aku pikirkan. Ini sangat buruk.

Justin
sumber
5

C

Kompilasi dengan flag -pthread (atau apa pun yang digunakan kompiler Anda).

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

Saya tidak yakin apakah ini memenuhi syarat atau tidak berdasarkan pada standar "waktu tidak diizinkan", karena pada dasarnya menggunakan penjadwal sebagai sumber entropi dengan sengaja mengabaikan keselamatan benang. Ia bekerja dengan menggunakan fungsi psuedo-random yang cukup mendasar ( generator bilangan acak Lehmer ) dengan seed awal hard coded. Itu kemudian mulai 20 utas yang semuanya menjalankan perhitungan Lehmer dengan satu set variabel bersama.

Tampaknya bekerja dengan cukup baik, berikut adalah beberapa kali berturut-turut:

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: Beri ini lebih banyak pemikiran dan sadari bahwa ini sama sekali bukan waktu. Bahkan dengan penjadwal yang sepenuhnya deterministik, entropi tidak datang dari irisan waktu - itu berasal dari pemuatan semua proses yang berjalan pada sistem.

EDIT 2 Setelah mengambil beberapa inspirasi dari @ Quincunx memposting kurva lonceng, saya membuang 12 MB keacakan file dan mengunggahnya ke CAcert . Itu gagal semua tes diehard, tetapi mencatat 7.999573 terhormat dari 8 pada tes THT (hanya berpotensi deterministik). Anehnya, menggandakan jumlah utas membuatnya semakin buruk.

Komintern
sumber
4

C

Ini menghasilkan angka acak dalam kisaran 0-255 dengan mengambil seed dari https://stackoverflow.com/questions menggunakan 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);
}

Contoh dijalankan:

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
izabera
sumber
2

C ++

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

keluaran

5 nomor acak

tiga sampel
masukkan deskripsi gambar di sini

masukkan deskripsi gambar di sini

masukkan deskripsi gambar di sini

Mukul Kumar
sumber
1
1, 2 dan 5 cukup dekat, pola yang sama berulang dalam ketiga contoh. tidak persis output yang diharapkan dari generator angka acak.
izabera
@izabera Ketika datang ke pointer dalam menghasilkan angka acak ... semuanya tergantung pada komputer Anda (RAM dan prosesor) mungkin alamat dimasukkan oleh 'int baru' ke 'ptr' sedang digunakan saat ini! Anda mencoba menjalankan kode ini?
Mukul Kumar
Biarkan saya menambahkan sedikit perubahan
Mukul Kumar
saya mencobanya sekarang, di komputer saya sepertinya saya selalu mendapatkan hal-hal seperti 11230576, 0, 11206992, 0, 2053725299, yang masih tidak tampak acak bagi saya.
izabera
check it out di ideone
izabera
2

perl

Apa semua sampah ini dengan mendapatkan benih melalui internet? Kedengarannya seperti menipu saya ;-) Saya lebih suka memberikan seed saya ke fungsi hash kriptografis, dan memberikan output dalam kisaran 0 hingga 2 ^ 160-1 seperti:

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'

Kapan pun Anda memiliki entropi dengan kualitas yang tidak pasti, cara untuk mendistribusikannya lebih teratur (tetapi tidak meningkatkan kualitasnya!) Adalah menyalurkannya ke SHA1 atau MD5 atau lebih, seperti yang telah saya lakukan di sini. Untuk benih pra-hash, saya telah menggunakan pid dan alamat referensi acak. Anda tentu saja dapat menambahkan input lain untuk entropi yang lebih banyak, misalnya pada x86 Anda dapat menggunakan TSC - (tetapi inlining kode assembly dalam perl agak sulit, jadi saya melewatkannya).

Jika Anda ingin memiliki output yang berbeda dari yang ada di komputer berikutnya, cukup sesuaikan "some_salt" menjadi string yang Anda sukai. Atau tinggalkan sama sekali jika Anda seorang minimalis =)

skibrianski
sumber
Saya rasa fungsi kriptografi apa pun yang layak namanya di pustaka standar menggunakan RNG yang aman secara kriptografis di dalam.
duci9y
Saya tidak yakin tentang itu. Digest :: MD5 / Digest :: SHA1 menghasilkan sepenuhnya, deterministik, output berulang, jadi untuk apa diperlukan angka acak?
skibrianski
Maaf! Saya baru saja terbang di atas jawaban Anda dan berpikir bahwa Anda menghasilkan kunci bukannya intisari.
duci9y
2

Jawa

Solusi saya menyalahgunakan hashCode()metode Objectkelas.

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

Output sampel:

31859448
22101035
11593610
4580332
25736626
32157998
3804398
32440180
19905449
2772678

Termotivasi oleh jawaban lain yang menunjukkan keacakan solusi, saya mengubah solusi saya untuk mengembalikan 16 bit tengah yang intdikembalikan oleh 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();
    }
}

Saya menghasilkan file 19 MB (terdiri dari 10 7 short ) dan mengirimkannya ke CACert . Berikut ini adalah screenshot dari hasilnya (telah diedit agar terlihat bagus, tetapi angkanya dibiarkan apa adanya):

Hasil

Saya terkejut dengan hasilnya, karena jam 7.999991 di tes Entropy dan lulus (?) Semua 7 tes Diehard.

n̴̖̋h̷͉̃a̷̭̿h̸̡̅ẗ̵̨́d̷̰̀ĥ̷̳
sumber
2

Javascript
Menghasilkan secara acak dengan gerakan mouse pengguna

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

Lima data terakhir yang disalin:
9637090187003
7828470680762
6045869361238
4220720695015
2422653391073

Vusan
sumber
1

Bash, rentang: int antara 0 dan 1

echo -n & echo "$! % 2" | bc
Keba
sumber
Jadi maksud Anda hanya mengambil 0 atau 1 saja?
Ya. Haruskah memenuhi "Angka yang dihasilkan dapat berada dalam kisaran berapa pun. Yah, setidaknya dua bilangan bulat yang berbeda: D", bukan?
Keba
Saya rasa begitu. Apakah Anda pikir Anda dapat memperluasnya ke rentang yang lebih besar?
Hanya echo -n & echo $!akan dilakukan, tetapi menjadi RNG yang sangat buruk. Anda juga dapat mengubah 2 dengan nomor lain, tetapi semakin besar angkanya, semakin buruk "keacakan".
Keba
Saya melihat. Terima kasih untuk penjelasannya.
1

Rubi

Sayangnya hanya Mac. Kami menggunakan soxuntuk menarik byte dari mikrofon (sebagai string, ahem ...), membalikkannya untuk mendapatkan status header di akhir (* batuk *), memotongnya, memotong kepala, mengambil MD5 dari potongan , parit karakter non-numerik dari hash, tambahkan bilangan bulat largish yang tersisa bersama, tempelkan 0.pada bagian depan, konversikan ke float, selesai.

Menghasilkan pelampung dengan panjang bervariasi pada interval 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
SLD
sumber
1

C

Menghasilkan secara acak menggunakan ID proses.

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

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

Output sampel:

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

BERPUTAR

Jika ini , saya akan menang!

byte a
?a@
Dokter
sumber
0

ular sanca

Keringkasan Python tidak pernah berhenti memukau. Karena menggunakan gambar acak imgur tampaknya tidak valid, saya telah menggunakan sumber keacakan yang hebat: obrolan 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 uji coba:

3258789746
1899058937
3811869909
274739242
1292809118

Tidak benar-benar acak tetapi sekali lagi tidak satupun dari ini.

qwr
sumber
saya pikir aturan 2 tidak mengizinkan url sepertiwhatever.com/random
izabera
@izabera 2 dari jawaban lain yang menggunakannya?
qwr
tidak, Anda secara eksplisit menggunakan konten yang dibuat secara acak. jawaban lainnya hanya akses ke beberapa halaman web non-acak untuk mendapatkan seed dan kemudian mencetak nomor acak.
izabera
@izabera Saya telah mengubah sumber acak saya. Apa yang Anda pikirkan sekarang?
qwr
sekarang tidak apa-apa: D
izabera
0

perl

Saya melihat banyak jawaban yang membuat permintaan HTTP, yang tampaknya sia-sia bagi saya karena di bawah selimut ada nomor acak yang diteruskan di kawat. Jadi saya memutuskan untuk menulis beberapa kode untuk menggeseknya di tingkat yang lebih rendah:

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

Memberikan port acak dalam kisaran 0..65535, secara teoritis. Dalam praktiknya, ada sejumlah port yang tidak akan Anda lihat, sehingga distribusinya jauh dari sempurna. Tapi itu, AFAICT jumlah minimal pekerjaan yang dapat Anda lakukan untuk mendapatkan beberapa entropi dari host jarak jauh yang memiliki port terbuka.

PS - Penanganan kesalahan dibiarkan sebagai latihan untuk pembaca ;-)

skibrianski
sumber
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;
}
VX
sumber