Ngẫu nhiên không có cơ sở thời gian [đóng]


9

Máy tính không ở ngoài nơi tạo ra các số ngẫu nhiên mà không có cơ sở, vì rất có thể, thời gian là cơ sở phổ biến của tính ngẫu nhiên.

Tôi muốn bạn tạo một mã tạo các số ngẫu nhiên với các quy tắc sau:

  • Thời gian không được phép là cơ sở, tại bất kỳ thời điểm nào của chương trình.
  • Các chức năng ngẫu nhiên / giả ngẫu nhiên được xác định trước không được phép.
  • Số được tạo có thể nằm trong bất kỳ phạm vi. Vâng ít nhất hai số nguyên khác nhau: D
  • Số được lặp lại.

2
Không rõ ý của bạn là gì "Số được tạo có thể nằm trong bất kỳ phạm vi nào". Bạn có nghĩa là lập trình viên được tự do chọn một phạm vi? Hoặc họ phải hỗ trợ bất kỳ phạm vi nào người dùng yêu cầu? Cả hai đều có vấn đề. Nếu người dùng yêu cầu một phạm vi, điều gì sẽ xảy ra nếu họ yêu cầu các số nằm ngoài giới hạn của các kiểu dữ liệu được xây dựng? Và nếu lập trình viên được tự do lựa chọn, tôi chọn số nguyên trong khoảng từ 1 đến 1 .: D
Jonathan Van Matre

2
Đáng lẽ phải là một môn đánh gôn ...
Mukul Kumar

Tôi bắt đầu câu hỏi này như câu hỏi phổ biến, liệu môn đánh gôn có phù hợp hơn với điều này không?
Dadan

@Daniel Vâng, nhưng hãy đặt câu hỏi này thành câu hỏi phổ biến và đăng câu hỏi mới với mã golf với các quy tắc mới (trên thế hệ ngẫu nhiên) sẽ rất vui
Mukul Kumar

1
sử dụng internet như một hạt giống có vẻ như gian lận phải không?
Dean MacGregor

Câu trả lời:


6

JavaScript

Đó là niềm vui!

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

Tôi đã viết lên Mersenne Twister trong JS. Sau đó, tôi nhận ra mình phải lấy một hạt giống từ đâu đó.

Vì vậy, tôi quyết định tôi sẽ lấy nó từ API Stack Exchange! (Tôi có thể sử dụng localStoragevà tăng một bộ đếm, nhưng điều đó không vui chút nào.) Vì vậy, tôi đã nắm được 10 câu trả lời gần đây nhất, và sau đó tôi chỉ lấy 4 hoặc ít hơn các chữ số liên tiếp trong câu trả lời và thêm chúng vào.

Các hạt này luôn khác nhau, vì Stack Overflow liên tục cập nhật (và hạn ngạch của tôi tiếp tục giảm!) Các số bao gồm ID câu trả lời, ID câu hỏi, điểm số, số lần tăng / giảm, số chủ sở hữu / ID và dữ liệu trình bao bọc (hạn ngạch và như vậy ). Trong một lần chạy tôi đã nhận 256845, sau đó 270495, và sau đó 256048, vv ....

Điều này ghi lại 10 số bổ sung hai bit 32 bit ngẫu nhiên vào bàn điều khiển. Đầu ra mẫu:

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

}

Điều kỳ diệu là trong public NoTimeRandom(). Mảng được truyền vào chuỗi có thể gây nhầm lẫn cho các lập trình viên mới, vì các số là ngẫu nhiên. Mẫu (đối với char[]: [C@4a8e91eb). Các nextphương pháp được sao chép từ java.util.Random.

Đầu ra mẫu:

134277366
467041052
-555611140
-1741034686
1420784423

Hãy kiểm tra tính hiệu quả của rng này:

Trong câu trả lời của tôi về Xấp xỉ một đường cong Bell , việc tạo dữ liệu tôi sử dụng phụ thuộc vào một rng tốt. Hãy chạy nó với cái này là rng. Đầu ra:

nhập mô tả hình ảnh ở đây

Đúng như tôi nghĩ. Đây là một rng khá tệ hại.


5

C

Biên dịch với cờ -pthread (hoặc bất cứ thứ gì trình biên dịch của bạn sử dụng).

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

Tôi không chắc chắn điều này có đủ điều kiện hay không dựa trên tiêu chuẩn "thời gian không được phép", bởi vì về cơ bản, nó sử dụng bộ lập lịch làm nguồn entropy bằng cách cố ý bỏ qua an toàn luồng. Nó hoạt động bằng cách sử dụng một hàm psuedo-Random khá cơ bản (trình tạo số ngẫu nhiên của Lehmer ) với một hạt giống ban đầu được mã hóa cứng. Sau đó, nó bắt đầu 20 luồng mà tất cả chạy tính toán Lehmer với một bộ biến được chia sẻ.

Có vẻ như hoạt động khá tốt, đây là một vài lần chạy liên tiếp:

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: Đã cho điều này thêm một chút suy nghĩ và nhận ra rằng đây hoàn toàn không phải là thời gian. Ngay cả với một bộ lập lịch hoàn toàn xác định, entropy không đến từ các lát cắt thời gian - nó đến từ việc tải tất cả các quy trình đang chạy trên hệ thống.

EDIT 2 Sau khi lấy một số cảm hứng từ @Quincunx đăng một đường cong hình chuông, tôi đã đổ 12MB ngẫu nhiên vào một tệp và tải nó lên CAcert . Nó đã thất bại trong tất cả các bài kiểm tra cực đoan, nhưng đã đạt được 7.999573 đáng nể trong số 8 bài kiểm tra ENT (chỉ có khả năng xác định). Thật kỳ lạ, nhân đôi số lượng chủ đề làm cho nó tồi tệ hơn.


4

C

Nó tạo ra một số ngẫu nhiên trong phạm vi 0-255 bằng cách lấy hạt giống từ https://stackoverflow.com/questions bằng cách sử dụng 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);
}

Chạy mẫu:

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

đầu ra

5 số ngẫu nhiên

ba mẫu
nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây

nhập mô tả hình ảnh ở đây


1
1, 2 và 5 khá gần nhau, cùng một mẫu được lặp lại trong cả 3 ví dụ. không chính xác đầu ra dự kiến ​​từ một trình tạo số ngẫu nhiên.
izabera

@izabera Khi nói đến con trỏ trong việc tạo số ngẫu nhiên ... mọi thứ phụ thuộc vào máy tính của bạn (RAM và bộ xử lý) có thể địa chỉ được cung cấp bởi 'new int' thành 'ptr' hiện đang được sử dụng! Bạn đã thử chạy mã này?
Mukul Kumar

Hãy để tôi thêm một chút thay đổi
Mukul Kumar

Tôi đã thử nó ngay bây giờ, trên máy của tôi có vẻ như tôi luôn nhận được những thứ như thế 11230576, 0, 11206992, 0, 2053725299, mà vẫn không có vẻ ngẫu nhiên đối với tôi.
izabera

kiểm tra nó tại ideone
izabera

2

perl

Tất cả những thứ rác rưởi này với việc lấy hạt giống qua internet là gì? Nghe có vẻ như gian lận đối với tôi ;-) Tôi thích đưa hạt giống của mình vào hàm băm mật mã thay vào đó và đưa ra đầu ra trong phạm vi 0 đến 2 ^ 160-1 như vậy:

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'

Bất cứ khi nào bạn có entropy chất lượng không chắc chắn, một cách để phân phối nó thường xuyên hơn (nhưng không làm tăng chất lượng của nó!) Là đưa nó vào như SHA1 hoặc MD5, như tôi đã làm ở đây. Đối với hạt tiền băm, tôi đã sử dụng pid và địa chỉ của một tham chiếu ngẫu nhiên. Tất nhiên bạn có thể thêm các đầu vào khác để có thêm entropy, ví dụ trên x86, bạn có thể sử dụng TSC - (nhưng mã lắp ráp nội tuyến trong perl là một chút của một con gấu, vì vậy tôi đã bỏ qua nó).

Nếu bạn muốn có đầu ra khác với anh chàng trên máy tính tiếp theo, chỉ cần điều chỉnh "some_salt" thành một chuỗi theo ý thích của bạn. Hoặc loại bỏ nó hoàn toàn nếu bạn là người tối giản =)


Tôi đoán rằng bất kỳ chức năng mã hóa nào có giá trị tên của nó trong một thư viện tiêu chuẩn đều sử dụng RNG bảo mật bằng mật mã trong nội bộ.
duci9y

Tôi không chắc về điều đó. Digest :: MD5 / Digest :: SHA1 tạo ra đầu ra hoàn toàn xác định, có thể lặp lại, vậy nó cần một số ngẫu nhiên để làm gì?
skibrianski

Lấy làm tiếc! Tôi vừa lướt qua câu trả lời của bạn và nghĩ rằng bạn đang tạo ra một khóa thay vì thông báo.
duci9y

2

Java

Giải pháp của tôi lạm dụng hashCode()phương pháp của Objectlớp.

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

Đầu ra mẫu:

31859448
22101035
11593610
4580332
25736626
32157998
3804398
32440180
19905449
2772678

Được thúc đẩy bởi câu trả lời khác thể hiện tính ngẫu nhiên của giải pháp, tôi đã thay đổi giải pháp của mình để trả về 16 bit giữa của inttrả về 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();
    }
}

Tôi đã tạo một tệp 19 MB (bao gồm 10 7 short ) và gửi nó cho CACert . Dưới đây là ảnh chụp màn hình của kết quả (nó đã được chỉnh sửa để trông đẹp mắt, nhưng các số còn lại như cũ):

Kết quả

Tôi đã rất ngạc nhiên với kết quả, vì nó đồng hồ 7.999991 trong bài kiểm tra Entropy và vượt qua (?) Tất cả 7 bài kiểm tra Diehard.


2

Javascript
Tạo ngẫu nhiên với di chuyển chuột của người dùng

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

Năm dữ liệu được sao chép gần đây nhất:
9637090187003
7828470680762
6045869361238
4220720695015
2422653391073


1

Bash, phạm vi: ints từ 0 đến 1

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

Vì vậy, bạn có nghĩa là nó chọn 0 hoặc 1 chỉ?

Vâng. Nên hoàn thành "Số được tạo có thể nằm trong bất kỳ phạm vi nào. Ít nhất hai số nguyên khác nhau: D", không nên sao?
Keba

Tôi đoán vậy. Bạn có nghĩ rằng bạn có thể mở rộng nó đến một phạm vi lớn hơn?

Chỉ cần echo -n & echo $!làm, nhưng là một RNG rất xấu. Bạn cũng có thể thay đổi 2 với bất kỳ số nào khác, nhưng số càng lớn, tệ hơn sẽ nhận được "tính ngẫu nhiên".
Keba

Tôi hiểu rồi. Cảm ơn đã giải thích.

1

Hồng ngọc

Thật không may Mac chỉ. Chúng tôi sử dụng soxđể kéo byte từ micrô (dưới dạng chuỗi, ahem ...), đảo ngược nó để lấy tiêu đề trạng thái ở cuối (* ho *), cắt nó ra, cắt tiêu đề, lấy MD5 của các đoạn , bỏ các ký tự không phải là số từ hàm băm, thêm các số nguyên lớn còn lại với nhau, dán một 0.mặt trước, chuyển đổi thành một số float, được thực hiện.

Tạo phao có độ dài khác nhau trên khoảng 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

Tạo ngẫu nhiên bằng cách sử dụng ID tiến trình.

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

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

Đầu ra mẫu:

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


0

trăn

Sự đồng nhất của Python không bao giờ hết ngạc nhiên. Vì việc sử dụng hình ảnh ngẫu nhiên của imgur rõ ràng không hợp lệ, tôi đã sử dụng một nguồn ngẫu nhiên tuyệt vời: trò chuyện của 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 thử nghiệm:

3258789746
1899058937
3811869909
274739242
1292809118

Không thực sự ngẫu nhiên nhưng sau đó một lần nữa không ai trong số này là.


tôi nghĩ quy tắc 2 không cho phép các url nhưwhatever.com/random
izabera

@izabera 2 trong số các câu trả lời khác đã sử dụng nó?
qwr

Không, bạn rõ ràng đang sử dụng nội dung được tạo ngẫu nhiên. các câu trả lời khác chỉ cần truy cập vào một số trang web không ngẫu nhiên để lấy hạt giống và sau đó in một số ngẫu nhiên.
izabera

@izabera Tôi đã thay đổi nguồn ngẫu nhiên của mình. Bạn nghĩ gì về nó bây giờ?
qwr

bây giờ thì ổn rồi: D
izabera

0

perl

Tôi đã thấy rất nhiều câu trả lời tạo ra các yêu cầu HTTP, điều này có vẻ lãng phí đối với tôi bởi vì dưới vỏ bọc có những con số ngẫu nhiên được chuyển qua trên dây. Vì vậy, tôi quyết định viết một số mã để vuốt một mã ở mức thấp hơn:

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

Cung cấp các cổng ngẫu nhiên trong phạm vi 0..65535, theo lý thuyết. Trong thực tế, có một số cổng bạn sẽ không bao giờ nhìn thấy, vì vậy việc phân phối không hoàn hảo. Nhưng đó là, AFAICT số lượng công việc tối thiểu bạn có thể làm để có được một số entropy từ một máy chủ từ xa có cổng mở.

PS - Xử lý lỗi được để lại như một bài tập cho người đọc ;-)


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;
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.