Generator PRNG skopiowany z wikipedii

0

Znalazłem kod:

https://en.wikipedia.org/wiki/Xorshift

struct xorshift64_state {
    uint64_t a;
};

uint64_t xorshift64(struct xorshift64_state *state)
{
	uint64_t x = state->a;
	x ^= x << 13;
	x ^= x >> 7;
	x ^= x << 17;
	return state->a = x;
}

I uruchomiłem go tak:

uint64_t a = 555;

uint64_t xorshift64(void)
{
    uint64_t x = a;
    x ^= x << 13;
    x ^= x >> 7;
    x ^= x << 17;
    return a = x;
}

int main()
{
    uint64_t result = 0;

    while (true)
    {
    result = xorshift64();
    //std::cout << result << "\n";
    }
}

Nie wiem jak uruchomić oryginalny kod. Co to znaczy, że funkcja przyjmuje jako argument struct xorshift64_state *state? Co to jest *state? Co ona właściwie przyjmuje jako argument? Co robi state->a? Przypisuje wartość state do a? Jeśli tak to po co jest to robione w dwóch miejscach kodu? state->a jest używane raczej jakby było jedną zmienną zapisaną w osobliwy sposób.

1

Pytasz o totalne podstawy, to trochę bez sensu, odpowiedzi na twoje pytania wiele ci nie dadzą, bo nie zrozumiesz je bez reszty podstaw.
Weź przeczytaj byle kurs.

#include <iostream>
using namespace std;

struct xorshift64_state { uint64_t a; };

uint64_t xorshift64(struct xorshift64_state *state)
{
	uint64_t x=state->a;
	x^=x<<13;
	x^=x>>7;
	x^=x<<17;
	return state->a = x;
}

xorshift64_state xorshift64state={42};

int main()
{
    while(true) cout<<xorshift64(&xorshift64state)<<endl;
    return 0;
}

Jednak skoro się posługujesz c++ to raczej coś w ten deseń:

#include <iostream>
#include <ctime>
using namespace std;

class xorshift64
{
	private:
	uint64_t &seed()const
	{
		static uint64_t Seed=42;
		return Seed;
	}
	public:
	uint64_t get()const { return this->seed(); }
	uint64_t set(uint64_t seed) { return this->seed()=seed; }
	xorshift64(uint64_t seed) { set(seed); }
	uint64_t next()
	{
		uint64_t x=get();
		x^=x<<13;
		x^=x>>7;
		x^=x<<17;
		return set(x);
	}
};

int main()
{
	xorshift64 rnd(time(0));
    while(true) cout<<rnd.next()<<endl;
    return 0;
}
0

Po co jedną zmienną definiować w strukturze?

Podobnie po co pisać tyle:

class xorshift64
{
	private:
	uint64_t &seed()const
	{
		static uint64_t Seed=42;
		return Seed;
	}
	public:
	uint64_t get()const { return this->seed(); }
	uint64_t set(uint64_t seed) { return this->seed()=seed; }
	xorshift64(uint64_t seed) { set(seed); }
	uint64_t next()

Skoro można napisać:

uint64_t seed = 42;

I prostą funkcję, w której jest generator. W Pythonie podejrzewam, że nikt by nie robił takich rzeczy. To są jakieś przyzwyczajenia charakterystyczne dla języka, czy ma to głębszy sens?

2
Tomasz_D napisał(a):

Po co jedną zmienną definiować w strukturze?
Podobnie po co pisać tyle:
I prostą funkcję, w której jest generator. W Pythonie podejrzewam, że nikt by nie robił takich rzeczy. To są jakieś przyzwyczajenia charakterystyczne dla języka, czy ma to głębszy sens?

  1. Zastanów się jak zaimplementujesz jeszcze 4 innych generatory każdy z których ma zmienną uint64_t seed = 42;.
  2. Zastanów się jak zaimplementujesz kilka wątków każdy z których ma mieć niezależny generator ale w każdym z wątków generator ma generować liczby losowe w tej samej kolejności, np dla przetestowania algorytmów sortowania.
0
_13th_Dragon napisał(a):
  1. Zastanów się jak zaimplementujesz jeszcze 4 innych generatory każdy z których ma zmienną uint64_t seed = 42;.

Może by nazwać je seed_1, seed_2 i tak dalej?

_13th_Dragon napisał(a):
  1. Zastanów się jak zaimplementujesz kilka wątków każdy z których ma mieć niezależny generator ale w każdym z wątków generator ma generować liczby losowe w tej samej kolejności, np dla przetestowania algorytmów sortowania.

Nie wiem jak się uruchamia kilka wątków, ale jeśli chcę sobie uruchomić dwa generatory robię tak:

#include <stdint.h>
#include <iostream>


uint64_t xorshift64(uint64_t a)
{
    uint64_t x = a;
    x ^= x << 13;
    x ^= x >> 7;
    x ^= x << 17;
    return x;
}

int main()
{
    uint64_t a = 3;
    uint64_t a_1 = 7;

    for(int i=0; i<1000; i++)
    {
    a = xorshift64(a);
    a_1 = xorshift64(a_1);
    
    std::cout << a << "\n";
    std::cout << a_1 << "\n";
    
    }
}


0

Najprostsza implementacja:

long int xorshift ()
{	static long int state = 123;
	state ^= state << 13;
	state ^= state >> 17;
	state ^= state << 5;
	return state;
}

Lub z wskaźnikiem:

long int xorshift (long int *statep)
#define	state	*statep
{	state ^= state << 13;
	state ^= state >> 17;
	state ^= state << 5;
	return state;
}
#undef	state
3
Tomasz_D napisał(a):

Znalazłem kod:

https://en.wikipedia.org/wiki/Xorshift

struct xorshift64_state {
    uint64_t a;
};

uint64_t xorshift64(struct xorshift64_state *state)
{
	uint64_t x = state->a;
	x ^= x << 13;
	x ^= x >> 7;
	x ^= x << 17;
	return state->a = x;
}

I uruchomiłem go tak:

uint64_t a = 555;

uint64_t xorshift64(void)
{
    uint64_t x = a;
    x ^= x << 13;
    x ^= x >> 7;
    x ^= x << 17;
    return a = x;
}

Oryginalny kod jest napisany w C, który na dodatek pogorszyłeś dodając ukryty globalny stan, co jest rozwiązaniem gorszym od orginalnego.
Przerabiając do c++:

class xorshift64 {
    uint64_t a;
public:
    xorshift64(uint64_t seed = 555) : a{seed}
    {}
    
    uint64_t next()
    {
    	uint64_t x = a;
    	x ^= x << 13;
    	x ^= x >> 7;
    	x ^= x << 17;
        a = x;
    	return x;
    }

    uint64_t operator()();
    {
        return next();
    }
};

Przeróbka z static uint64_t Seed=42; od @_13th_Dragon też doje ukryty globalny stan (lepiej ukryty).

0
_13th_Dragon napisał(a):

Pytasz o totalne podstawy, to trochę bez sensu, odpowiedzi na twoje pytania wiele ci nie dadzą, bo nie zrozumiesz je bez reszty podstaw.
Weź przeczytaj byle kurs.

Kursy mówią mniej więcej tyle: jest sobie struktura, coś w niej możemy umieścić, koniec. Zresztą nie wierzę, że programowania można się nauczyć z kursów (internetowych poradników). Nie nauczyłem się nigdy żadnej rzeczy z poradnika. Zawsze albo ktoś tłumaczył co robi dana rzecz i dlaczego, albo patrzyłem jak działa program wiedząc dosyć dokładnie co robi/ma robić. Dopiero później dowiadywałem się, że to ma jakąś nazwę i ewentualnie inne zastosowania.

1 użytkowników online, w tym zalogowanych: 0, gości: 1