Zaman Temelli Rastgele [kapalı]


9

Bilgisayarlar hiçbir yerde rastgele sayılar oluşturmazlar, büyük olasılıkla zaman, rasgeleliğin evrensel temelidir.

Bu kurallar ile rasgele sayılar oluşturan bir kod oluşturmak istiyorum:

  • Zamanın, programın hiçbir noktasında temeli olması yasaktır.
  • Önceden tanımlanmış rastgele / sözde rastgele işlevlere izin verilmez.
  • Oluşturulan sayılar herhangi bir aralıkta olabilir. En az iki farklı tamsayı: D
  • Sayılar yankılanır.

2
"Oluşturulan sayılar herhangi bir aralıkta olabilir" ile ne demek istediğiniz belirsizdir. Yani kodlayıcı bir aralık seçmekte özgür mü demek istiyorsun? Veya kullanıcının istediği herhangi bir aralığı desteklemeleri mi gerekiyor? Her ikisi de sorunlu. Kullanıcı bir aralık isterse, yerleşik veri türlerinin sınırları dışında sayılar isterse ne olur? Kodlayıcıyı seçmek serbestse, 1 ile 1 arasında bir tamsayı seçerim.: D
Jonathan Van Matre

2
Kod golf olmalıydı ...
Mukul Kumar

Bu soruya popülerlik sorusu olarak başladım, kod golf buna daha uygun mu?
Dadan

@Daniel Evet ama bu soru popülerlik sorusu olsun ve eğlenceli olacak yeni kurallarla (rastgele nesil) kod golf ile yeni bir soru yayınlayın
Mukul Kumar

1
interneti bir tohum olarak kullanmak hile gibi görünüyor değil mi?
Dean MacGregor

Yanıtlar:


6

JavaScript

Bu eğlenceliydi!

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

JS'de Mersenne Twister'ı yazdım. Sonra bir yerden tohum almam gerektiğini fark ettim.

Bu yüzden, Stack Exchange API'sından alacağıma karar verdim! ( localStorageBir sayacı kullanabilir ve arttırabilirim, ama bu eğlenceli değil.) Böylece, en son 10 aktif yanıtı aldım ve sonra her 4 veya daha az ardışık basamağı yanıtladım ve ekledim.

Bu tohumlar her zaman farklıdır; ). Bir koşuda 256845, sonra 270495, ve sonra 256048, vb.

Bu, 10 rasgele 32 bit ikinin tamamlayıcı sayısını konsola kaydeder. Örnek çıktı:

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

}

Sihir public NoTimeRandom(). Dizelere dökülen diziler, sayılar rasgele olduğundan yeni programcıları karıştırabilir. (İçin Örnek char[]: [C@4a8e91eb). nextYöntem kopyalanır java.util.Random.

Örnek çıktı:

134277366
467041052
-555611140
-1741034686
1420784423

Bu rng'in etkinliğini test edelim:

Gelen cevabım bir çan eğrisi meydana , ben kullanılan veri nesil iyi RNG bağlıdır. Bunu rng olarak çalıştıralım. Çıktı:

resim açıklamasını buraya girin

Tam düşündüğüm gibi. Bu oldukça berbat bir rng.


5

C

-Pthread bayrağını (veya derleyicinizin kullandığı her şeyi) derleyin.

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

Bu temelde zamanlayıcı zamanlama entropi kaynağı olarak entropi kaynağı olarak kasıtlı olarak iş parçacığı güvenliğini göz ardı ederek kullanarak, "zaman izin verilmez" standardı dayalı olup olmadığını emin değilim. Sert kodlanmış bir başlangıç ​​tohumuna sahip oldukça basit bir psuedo-random fonksiyonu ( Lehmer rasgele sayı üreteci ) kullanarak çalışır . Daha sonra, Lehmer hesaplamasını paylaşılan bir değişkenler kümesiyle çalıştıran 20 iş parçacığı başlar.

Oldukça iyi çalışıyor gibi görünüyor, burada birkaç ardışık koşu var:

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: Bunu biraz daha düşünerek verdi ve bunun hiç zamana dayalı olmadığını fark etti. Tamamen deterministik bir zamanlayıcı ile bile, entropi zaman dilimlerinden gelmez - sistemdeki tüm çalışan işlemlerin yüklenmesinden gelir.

2 DÜZENLEME @Quincunx bir çan eğrisi göndererek biraz ilham aldıktan sonra, bir dosyaya 12MB rasgele döktüm ve CAcert'e yükledim . Tüm diehard testlerinde başarısız oldu, ancak ENT testinde 8 üzerinden 7.999573'e dikkat çekti (sadece Potansiyel olarak deterministik). İlginçtir ki, iplik sayısının iki katına çıkarılması durumu daha da kötüleştirdi.


4

C

Bu tohum alarak 0-255 aralığında bir rasgele bir sayı oluşturur https://stackoverflow.com/questions kullanılarak 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);
}

Örnek çalışma:

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

çıktı

5 rastgele sayı

üç örnek
resim açıklamasını buraya girin

resim açıklamasını buraya girin

resim açıklamasını buraya girin


1
1, 2 ve 5'inci oldukça yakın, aynı örnek 3 örnekte de tekrarlanmıştır. tam olarak rastgele bir sayı üretecinden beklenen çıktı değil.
izabera

@izabera Rastgele sayılar üretmede işaretçiler söz konusu olduğunda ... her şey bilgisayarınıza (RAM ve işlemciye) bağlıdır, belki 'new int' tarafından 'ptr' içine beslenen adres şu anda kullanılıyor! Bu kodu çalıştırmayı denediniz mi?
Mukul Kumar

Biraz değişiklik ekleyeyim
Mukul Kumar

şimdi denedim, makinemde her zaman gibi şeyler alıyorum gibi görünüyor 11230576, 0, 11206992, 0, 2053725299, ki bu hala bana rastgele gelmiyor.
izabera


2

perl

İnternet üzerinden tohum elde etmenin tüm çöpleri neler? Bana hile gibi geliyor ;-) Onun yerine bir kriptografik karma işlevine tohum vermek ve 0 ila 2 ^ 160-1 aralığında çıktı vermek için tercih ederim:

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'

Belirsiz kalite entropisine sahip olduğunuzda, onu daha düzenli bir şekilde dağıtmanın (ancak kalitesini artırmanın değil!) Bir yolu, burada yaptığım gibi SHA1 veya MD5 veya benzeri gibi borulara bağlamaktır. Hash öncesi tohumlar için pid ve rastgele bir referans adresi kullandım. Tabii ki daha fazla entropi için başka girişler ekleyebilirsiniz, örneğin x86'da TSC kullanabilirsiniz - (ancak perl'de satır içi montaj kodu biraz ayı, bu yüzden atladım).

Bir sonraki bilgisayardaki adamdan farklı bir çıktıya sahip olmak istiyorsanız, "some_salt" ı istediğiniz gibi bir dize olarak ayarlayın. Veya minimalist biriyseniz dışarıda bırakın =)


Standart bir kütüphanede ismine değer veren herhangi bir kriptografik fonksiyonun, kriptografik olarak güvenli bir RNG'yi dahili olarak kullandığını tahmin ediyorum.
duci9y

Bunun hakkında emin değilim. Digest :: MD5 / Digest :: SHA1 tamamen deterministik, tekrarlanabilir çıktı üretir, bu yüzden rastgele bir sayıya ne ihtiyaç duyar?
skibrianski

Afedersiniz! Sadece cevabını uçurdum ve sindirmek yerine anahtar ürettiğini düşündüm.
duci9y

2

Java

Benim çözümüm sınıf hashCode()yöntemini kötüye kullanıyor Object.

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

Örnek çıktı:

31859448
22101035
11593610
4580332
25736626
32157998
3804398
32440180
19905449
2772678

Çözümün rastgele olduğunu gösteren diğer cevaplayanlar tarafından motive edildim, intgeri dönenin orta 16 bitini döndürmek için çözümümü değiştirdim 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();
    }
}

19 MB'lık bir dosya (10 7'den oluşan short) oluşturdum ve CACert'e gönderdim . İşte sonucun ekran görüntüsü ( güzel görünmek için düzenlendi, ancak sayılar olduğu gibi bırakıldı):

Sonuç

Entropi testinde 7.999991 saatini alır ve 7 Diehard testinin tümünü (?) Geçtiği için sonuçta şaşırdım.


2

Javascript
Kullanıcı fare hareketi ile rastgele oluşturma

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

Son beş kopyalanan veri:
9637090187003
7828470680762
6045869361238
4220720695015
2422653391073


1

Bash, aralık: 0 ile 1 arasında ints

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

Yani sadece 0 ya da 1'i mi seçiyorsun?

Evet. "Üretilen sayılar herhangi bir aralıkta olabilir. Peki en az iki farklı tamsayı: D" olmalı, değil mi?
Mart'ta Keba

Sanırım öyle. Sizce onu daha geniş bir aralığa genişletebilirsiniz?

Sadece echo -n & echo $!yapacak, ama çok kötü bir RNG olun. Ayrıca 2'yi başka bir sayıyla da değiştirebilirsiniz, ancak sayı büyüdükçe "rasgelelik" daha da kötüleşir.
Mart'ta Keba

Anlıyorum. Açıklama için teşekkürler.

1

Yakut

Ne yazık ki sadece Mac. soxMikrofondan bayt çekmek için kullanırız (dize, ahem ...), durum üstbilgisini sonuna (* öksürük) almak için tersine çevirir, keseriz, başlığı keseriz, parçaların MD5'ini alırız , sayısal olmayan karakterleri karmadan çıkarın, kalan largayı tamsayıları bir araya getirin, öne yapıştırın 0., bir kayan noktaya dönüştürün, bitti.

Aralıkta değişen uzunlukta şamandıralar oluşturur 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

İşlem kimliği kullanarak rastgele oluşturma.

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

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

Örnek çıktı:

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


0

piton

Python'un kıskançlığı asla hayret etmeyi bırakmaz. İmgur'un rastgele görüntüsünü kullanmak görünüşte geçerli olmadığından, büyük bir rastgele kaynak kullandım: stackoverflow'un sohbeti!

   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 deneme:

3258789746
1899058937
3811869909
274739242
1292809118

Gerçekten rastgele değil ama sonra yine bunların hiçbiri.


i kural 2 gibi url izin vermez düşünüyorumwhatever.com/random
izabera

@izabera diğer cevapların 2'sini kullandı mı?
qwr

hayır, açıkça rastgele oluşturulmuş içerik kullanıyorsunuz. diğer cevaplar sadece bir tohum almak ve rastgele bir sayı yazdırmak için bazı rastgele olmayan web sayfasına erişim.
izabera

@izabera Rastgele kaynağımı değiştirdim. Şimdi ne düşünüyorsun?
qwr

şimdi iyi: D
izabera

0

perl

HTTP istekleri yapan, benim için savurgan görünen birçok cevap gördüm, çünkü kapakların altında tel üzerinde rasgele sayılar var. Bu yüzden daha düşük bir seviyede kaydırmak için bazı kod yazmaya karar verdim:

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

Teorik olarak 0..65535 aralığında rastgele portlar verir. Pratikte, asla göremeyeceğiniz birkaç liman vardır, bu yüzden dağıtım mükemmel olmaktan uzaktır. Ancak, açık bir bağlantı noktası olan uzak bir ana bilgisayardan entropi elde etmek için yapabileceğiniz minimum iş miktarını AFAICT.

PS - Hata işleme, okuyucuya bir alıştırma olarak bırakılır ;-)


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;
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.