시간 기준이없는 랜덤 [닫힘]


9

컴퓨터는 어디에서나 근거없이 임의의 숫자를 생성하지 않습니다. 대부분의 경우 시간은 임의의 기본입니다.

다음 규칙을 사용하여 난수를 생성하는 코드를 작성하고 싶습니다.

  • 프로그램의 어느 시점에서나 시간이 기초가 될 수는 없습니다.
  • 사전 정의 된 임의 / 의사 난수 함수는 허용되지 않습니다.
  • 생성 된 숫자는 임의의 범위 내에있을 수 있습니다. 적어도 두 개의 다른 정수 : D
  • 숫자가 에코됩니다.

2
"생성 된 숫자는 임의의 범위 내에있을 수 있습니다"라는 의미가 무엇인지 확실하지 않습니다. 코더가 범위를 자유롭게 선택할 수 있습니까? 또는 사용자가 요청한 모든 범위를 지원해야합니까? 둘 다 문제가 있습니다. 사용자가 범위를 요청하는 경우 내장 데이터 형식의 범위를 벗어난 숫자를 요청하면 어떻게됩니까? 그리고 코더가 자유롭게 선택할 수 있다면, 나는 1과 1 사이의 정수를 선택합니다. : D
Jonathan Van Matre

2
코드 골프

나는이 질문을 인기 질문으로 시작했습니다. 코드 골프가 더 적합할까요?
Dadan

하지만 그래 @Daniel 재미있을거야이 질문에 인기-질문하자 및 (임의 세대) 새로운 규칙과 코드 골프에 새로운 질문을 게시
Mukul을 쿠마

1
인터넷을 씨앗으로 사용하는 것이 부정 행위처럼 보이지 않습니까?
Dean MacGregor 2

답변:


6

자바 스크립트

재밌었어요!

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에서 Mersenne Twister를 작성했습니다. 그런 다음 어딘가에서 씨앗을 얻어야한다는 것을 깨달았습니다.

그래서 Stack Exchange API에서 가져 오기로 결정했습니다! ( localStorage카운터를 사용 하고 늘릴 수는 있지만 재미 있지는 않습니다.) 따라서 가장 최근에 활성화 된 10 개의 답을 잡고 응답에서 연속 된 4 자리 이하의 숫자를 취하여 더했습니다.

스택 오버플로가 지속적으로 업데이트되므로 할당량이 계속 감소하기 때문에 이러한 시드는 항상 다릅니다. 여기에는 응답 ID, 질문 ID, 점수, 상 / 하향 투표 수, 소유자 담당자 / ID 및 래퍼 데이터 (인수 등)가 포함됩니다. ). 하나 실행에 내가 가진 256845270495, 다음 256048등 ....

콘솔에 임의의 32 비트 2의 보수 번호 10 개를 기록합니다. 샘플 출력 :

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

5

자바

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

}

마법은에 있습니다 public NoTimeRandom(). 문자열로 캐스트 된 배열은 숫자가 임의이므로 새 프로그래머를 혼동시킬 수 있습니다. (샘플 char[]: [C@4a8e91eb). 이 next메소드는에서 복사됩니다 java.util.Random.

샘플 출력 :

134277366
467041052
-555611140
-1741034686
1420784423

이 rng의 효과를 테스트 해 봅시다 :

에서 내 대답 벨 대략적인 곡선 , 내가 사용하는 데이터 생성은 좋은의 RNG에 따라 달라집니다. 이것을 rng로 실행 해 봅시다. 산출:

여기에 이미지 설명을 입력하십시오

내가 생각한대로 이것은 꽤 시끄러운 rng입니다.


5

-pthread 플래그 (또는 컴파일러가 사용하는 모든 것)로 컴파일하십시오.

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

이것이 기본적으로 스레드 안전을 무시하여 스케줄러를 엔트로피의 소스로 사용하기 때문에 "시간이 허용되지 않음"표준에 따라 자격이 있는지 여부를 잘 모르겠습니다. 하드 코딩 된 초기 시드와 함께 상당히 기본적인 의사 난수 함수 ( Lehmer 난수 생성기 )를 사용하여 작동합니다 . 그런 다음 모두 공유 변수 세트로 Lehmer 계산을 실행하는 20 개의 스레드를 시작합니다.

상당히 잘 작동하는 것 같습니다. 다음은 두 번의 연속 실행입니다.

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

편집 : 이것을 조금 더 생각하고 이것이 시간 기반이 아님을 깨달았습니다. 완전히 결정론적인 스케줄러를 사용하더라도 엔트로피는 시간 조각에서 오는 것이 아니라 시스템에서 실행중인 모든 프로세스를로드하여 발생합니다.

편집 2 벨 커브를 게시하는 @Quincunx에서 영감을 얻은 후 12MB의 임의성을 파일에 덤프하고 CAcert에 업로드했습니다 . 모든 치열한 테스트에 실패했지만 ENT 테스트에서 8 개 중 7.999573 개를 기록했습니다 ( 잠재적으로 결정적 임). 흥미롭게도 스레드 수를 두 배로 늘리면 문제가 악화되었습니다.


4

를 사용하여 https://stackoverflow.com/questions 에서 시드를 가져 와서 0-255 범위의 난수를 생성합니다 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);
}

샘플 실행 :

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

산출

5 개의 난수

세 개의 샘플
여기에 이미지 설명을 입력하십시오

여기에 이미지 설명을 입력하십시오

여기에 이미지 설명을 입력하십시오


1
첫 번째, 두 번째 및 다섯 번째는 세 가지 예 모두에서 반복되는 동일한 패턴입니다. 난수 생성기의 예상 출력이 아닙니다.
izabera

@izabera 난수 생성에 대한 포인터에 관해서는 ... 모든 것이 컴퓨터 (RAM 및 프로세서)에 달려 있습니다 .'new int '가'ptr '에 제공 한 주소가 현재 사용되고 있습니다! 이 코드를 실행하려고 했습니까?
Mukul Kumar

약간의 변화를 추가하겠습니다
Mukul Kumar

나는 지금 그것을 시도했다, 내 컴퓨터에서 그것은 항상 11230576, 0, 11206992, 0, 2053725299나에게 무작위로 보이지 않는 것 같은 것을 얻는 것처럼 보인다.
izabera


2

인터넷을 통해 씨앗을 얻는이 쓰레기는 무엇입니까? 나에게 바람을 피우는 것처럼 들린다 ;-) 대신 내 시드를 암호화 해시 함수에 제공하고 0 ~ 2 ^ 160-1 범위의 출력을 선호합니다.

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'

불확실한 품질에 대한 엔트로피를 가질 때마다 더 정기적으로 배포하는 방법은 (품질을 높이 지 않는 것입니다!) 여기에서 한 것처럼 SHA1 또는 MD5 등으로 파이프를 파이프하는 것입니다. 사전 해시 시드의 경우 pid와 임의 참조 주소를 사용했습니다. 물론 더 많은 엔트로피를 위해 다른 입력을 추가 할 수 있습니다. 예를 들어 x86에서는 TSC를 사용할 수 있습니다 (그러나 perl의 어셈블리 코드 인라인은 약간의 곰이므로 건너 뛰었습니다).

다음 컴퓨터에서 다른 사람과 다른 출력을 원하면 "some_salt"를 원하는 문자열로 조정하십시오. 또는 미니멀리스트 인 경우 완전히 제외하십시오 =)


표준 라이브러리에서 이름이 가치가있는 암호화 기능은 내부적으로 암호로 안전한 RNG를 사용한다고 생각합니다.
duci9y

나는 그것에 대해 확실하지 않다. Digest :: MD5 / Digest :: SHA1은 완전히 결정적이고 반복 가능한 출력을 생성하므로 임의의 숫자가 필요한 이유는 무엇입니까?
skibrianski

죄송합니다! 방금 답변을 날아가서 다이제스트 대신 키를 생성한다고 생각했습니다.
duci9y

2

자바

내 솔루션 hashCode()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());
        }
    }
}

샘플 출력 :

31859448
22101035
11593610
4580332
25736626
32157998
3804398
32440180
19905449
2772678

솔루션의 임의성을 보여주는 다른 답변의 동기에 의해,에서 반환 된의 16 비트 중간을 반환하도록 솔루션을 변경 int했습니다 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();
    }
}

19MB 파일 (10 7 로 구성됨)을 생성 short하여 CACert에 제출했습니다 . 결과 의 스크린 샷은 다음과 같습니다 (멋지게 보이도록 편집되었지만 숫자는 그대로 남아 있습니다).

결과

엔트로피 테스트에서 7.999991을 클럭하고 7 개의 다이 하드 테스트를 모두 통과 (?)하기 때문에 결과에 놀랐습니다.


2


사용자 마우스 이동으로 임의의 자바 스크립트 생성

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

최근 5 개의 복사 된 데이터 :
9637090187003
7828470680762
6045869361238
4220720695015
2422653391073


1

배쉬, 범위 : 0과 1 사이의 정수

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

따라서 0 또는 1 만 선택한다는 의미입니까?

네. "생성 된 수는 임의의 범위 내에있을 수 있습니다. 적어도 두 개의 다른 정수 : D"를 충족시켜야합니까?
Keba

나는 그렇게 생각한다. 더 큰 범위로 확장 할 수 있다고 생각하십니까?

그냥 echo -n & echo $!할 것이지만 매우 나쁜 RNG입니다. 다른 숫자로 2를 변경할 수도 있지만 숫자가 클수록 "무작위"가 나빠집니다.
Keba

내가 참조. 설명 주셔서 감사합니다.

1

루비

불행히도 맥만. 우리 sox는 마이크에서 바이트 (줄, 헴 ...)를 가져 와서 뒤집어서 끝의 상태 헤더 (* 기침 *)를 가져 와서 잘라 내고 헤더를 잘라 내고 청크의 MD5를 가져옵니다 , 해시에서 숫자가 아닌 문자를 버리고 나머지 largish 정수를 함께 추가 0.하고 앞에 a 를 붙인 다음 float로 변환하십시오.

간격에 따라 다양한 길이의 부동 소수점을 생성합니다 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

프로세스 ID를 사용하여 무작위 생성

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

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

샘플 출력 :

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


0

파이썬

파이썬의 간결함은 결코 놀라지 않습니다. imgur의 임의 이미지를 사용하는 것은 분명히 유효하지 않기 때문에 나는 큰 임의의 소스를 사용했습니다 : stackoverflow 's chat!

   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 회 시도 :

3258789746
1899058937
3811869909
274739242
1292809118

실제로 무작위는 아니지만 다시는 이것들 중 어느 것도 아닙니다.


나는 규칙 2가 같은 URL을 허용하지 않는다고 생각합니다whatever.com/random
izabera

@izabera 2 다른 답변이 사용 되었습니까?
qwr

아니요, 임의로 생성 된 콘텐츠를 명시 적으로 사용하고 있습니다. 다른 답변은 무작위가 아닌 웹 페이지에 액세스하여 시드를 얻은 다음 임의의 숫자를 인쇄합니다.
izabera

@izabera 무작위 소스를 변경했습니다. 지금 어떻게 생각하세요?
qwr

: 괜찮아 : D
izabera

0

HTTP 요청을하는 많은 답변을 보았습니다. 커버 아래에서 전선에 임의의 숫자가 전달되기 때문에 나에게 낭비 인 것 같습니다. 그래서 나는 더 낮은 레벨에서 하나를 슬쩍하는 코드를 작성하기로 결정했습니다.

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

이론적으로 0..65535 범위의 임의 포트를 제공합니다. 실제로는 볼 수없는 많은 포트가 있으므로 배포가 완벽하지 않습니다. 그러나 AFAICT는 포트가 열려있는 원격 호스트에서 엔트로피를 얻는 데 필요한 최소한의 작업입니다.

PS-오류 처리는 독자에게 연습으로 남습니다.


0

// 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;
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.