Чем моя реализация PRNG отличается от той, которую я пытаюсь скопировать?

Мне нужен PRNG для проекта моделирования, и нашел ресурс что, учитывая мое ограниченное, но не несуществующее знание PRNG, кажется обоснованным и хорошо информированным. Я пытаюсь инкапсулировать алгоритмы, приведенные в этом отчете, в класс, но по некоторым причинам я получаю много повторяющихся значений. Может быть, просто то, что PRNG не так хорош, как говорится в отчете, но я подозреваю, что в моей реализации что-то не так.

Фон: код PRNG из отчета

Следующий пример кода приведен на странице 3:

/* Public domain code for JKISS RNG */
// seed variables
static unsigned int x = 123456789,y = 987654321,z = 43219876,c = 6543217;

unsigned int JKISS()
{
unsigned long long t;
x = 314527869 * x + 1234567;
y ^= y << 5; y ^= y >> 7; y ^= y << 22;
t = 4294584393ULL * z + c; c = t >> 32; z = t;
return x + y + z;
}

В связи с этим в докладе утверждается, что

Период JKISS составляет ≈2 127 = 1,7×10 38 (2 32 x (2 32 -1) x (1/2 *)
4294584393 x 2 32 — 1)) и он проходит все тесты Dieharder и полный набор тестов BigCrunch в
Testu01.

так что это определенно кажется мне достаточно хорошим. Далее в отчете (стр. 6) говорится

Следующий код C генерирует [sic] случайное число (с двойной точностью) с плавающей запятой 0 <= х < 1:

double x;
x = JKISS() / 4294967296.0;

Моя инкапсуляция этого в классе

У меня есть следующее в заголовочном файле:

class JKISS : public IPRNG {
private:
// Seed variables
static unsigned int x;
static unsigned int y;
static unsigned int z;
static unsigned int c;public:
static unsigned int randui32();
static double randdouble();
};

со следующим файлом реализации

#include "prng.hpp"
unsigned int JKISS::x = 123456789;
unsigned int JKISS::y = 987654321;
unsigned int JKISS::z = 43219876;
unsigned int JKISS::c = 6543217;

unsigned int JKISS::randui32() {
unsigned long long t;
x = 314527869 * x + 1234567;
y ^= y << 5; y ^= y >> 7; y ^= y << 22;
t = 4294584393ULL * z + c; c = t >> 32; z = t;
return x + y + z;
}

double JKISS::randdouble() {
return randui32() / 4294967296.0;
}

и следующая основная программа

#include <iostream>
#include "prng.hpp"
int main() {
for (int i = 0; i < 10000; ++i) {
std::cout << JKISS::randdouble() << std::endl;
}
}

Как видите, я скопировал большую часть кода.

Однако, когда я запускаю это, я получаю 68 повторяющихся значений, хотя я просто извлекаю 10 000 значений. Это говорит мне о том, что что-то не так с моей инкапсуляцией, но я не могу понять, в чем проблема.

В случае, если это имеет значение, я использую GCC 4.8.1 в Ubuntu 13.10 со следующими характеристиками:

Platform Info:
System: Linux (x86_64-linux-gnu)
CPU: Intel(R) Xeon(R) CPU           E5410  @ 2.33GHz
WORD_SIZE: 64

Любые идеи относительно того, что может вызвать это, приветствуются.

0

Решение

Я получаю те же результаты, что и вы, но без дубликатов; p

Я имею в виду, что если я запускаю вашу программу в соответствии с указаниями, я получу 68 дубликатов, но если я переключусь randdouble() => randui32() дубликатов больше нет, поэтому держу пари, что они были артефактом из-за точности процедуры печати.

Вы можете попытаться собрать двойные значения в массиве и сравнить их, чтобы убедиться на 100%.

0

Другие решения

Вы возвращаете floatв то время как оригинальный код генерирует double,

1

Зачем? Что заставляет вас думать, что какая-то случайная страница в Интернете даст вам лучшую ГСЧ, чем те, которые встроены в вашу стандартную библиотеку C ++, которая предоставляет все виды отличных функций, упакованных и готовых к использованию? Ты действительно в состоянии оценить, если то, что вы нашли, лучше для ваших целей?

0

Похоже, что напечатанный вывод составляет всего шесть значащих цифр, что означает, что у вас есть что-то вроде 1000000 уникальных значений отображения (это упрощено — есть больше возможностей, но распределение искажено). Фактически вы печатаете 10000 значений из пула 1000000. I считать 68 дубликатов разумно в этой ситуации.

0
По вопросам рекламы [email protected]