• Najnowsze pytania
  • Bez odpowiedzi
  • Zadaj pytanie
  • Kategorie
  • Tagi
  • Zdobyte punkty
  • Ekipa ninja
  • IRC
  • FAQ
  • Regulamin
  • Książki warte uwagi

liczby losowe, ale nie pseudo

VPS Starter Arubacloud
0 głosów
5,426 wizyt
pytanie zadane 9 grudnia 2015 w C i C++ przez Avernis Nałogowiec (27,400 p.)
Potrzebuję losowania liczb, ale nie pseudo. Da się to jakoś zrobić?

13 odpowiedzi

+4 głosów
odpowiedź 9 grudnia 2015 przez Sebastian Fojcik Nałogowiec (43,020 p.)
edycja 9 grudnia 2015 przez Sebastian Fojcik

Wszystkie algorytmy losujące to oszustwo.

Zawsze będziemy oszukiwani przez matematyczne algorytmy.

Napisałem prosty kod, który to sprawdzi. Losuje 1000 liczb z zakresu od 1 do 100 i potem bierze średnia arytmetyczną tych liczb. Rozpatrujemy 5 przypadków dla 3 typów losowań. Średnia zawsze będzie utrzymywana koło liczby 50. Wylosowałem 1000 liczb losowych 5 razy i za każdym razem średnia wynosi 50? Słaba ta losowość prawda?

Na zwykłym komputerze nie osiagniemy prawdziwej losowości. Nie ma lepszych i gorszych losowań. Wszystkie są tak samo oszukane :-)

#include <iostream>
#include <conio.h>
#include <random>
#include <cstdlib>
#include <ctime>

using namespace std;

double losuj1()
{
	double suma = 0;
	std::default_random_engine generator;
	std::uniform_int_distribution<int> distribution( 1, 100 );
	for( int i = 0; i < 1000; i++ )
	{
		int wylosowana = distribution( generator );
		suma += wylosowana;
	}
	return suma / 1000;
}

double losuj2()
{
	double suma = 0;
	std::random_device dev;
	std::mt19937 gen( dev() ); // Generator
	for( int i = 0; i < 1000; i++ )
	{
		int wylosowana = gen()%101 + 1;
		suma += wylosowana;
	}
	return suma / 1000;
}

double losuj3()
{
	double suma = 0;
	
	for( int i = 0; i < 1000; i++ )
	{
		int wylosowana = rand()%101 + 1;
		suma += wylosowana;
	}
	return suma / 1000;
}

int main()
{
	srand( time( NULL ) );
	for( int i = 0; i < 5; i++ )
		cout << "Losowanie typ 1 (test " << i + 1 << ") " << losuj1() << endl;
	for( int i = 0; i < 5; i++ )
		cout << "Losowanie typ 2 (test " << i + 1 << ") " << losuj2() << endl;
	for( int i = 0; i < 5; i++ )
		cout << "Losowanie typ 3 (test " << i + 1 << ") " << losuj3() << endl;

	_getch();
	return 0;
}

Odpalcie program 100 razy i jeżeli kiedykolwiek średnia spadnie poniżej 40, to szukajcie gwiazdy betlejemskiej, bo to będzie cholerny cud.

Możecie też zamknąć wszystko w pętli, która będzie się powtarzać dopóki średnia będzie między 45 a 55. Gwarantuję, że nigdy się nie skończy, bo losowość z tego żadna. 

Z matematycznego punktu widzenia możliwy jest przypadek, w którym wylosuje się 1000 liczb tych samych. To jest prawdziwa losowość, a nie takie funkcje pseudolosujące Pfff :-P

Wynik działania programu jakby komuś nie chciało się kompilować:

Przypominam, że 15 razy losowałem trzema różnymi sposobami. Łącznie 15 tysięcy liczb losowych z przedziału od 1 do 100. Średnia zawsze bliska połowie zakresu losowania, czyli oszustwo a nie losowanie :D

komentarz 7 maja 2016 przez Artur Wraga Obywatel (1,870 p.)
Wiesz ... sądzę że w rzeczywistości gdybyś włożył kulki z numerami do pudełka i ręcznie byś wyciągał tez będzie średnia 50. Prawodopobienstwo ze wymieszać liczbę mniejsza niż 50 jest takie samo jak to ze wymiesz większą niż 50 ... to tak jak byś miał tylko 2 liczby 1 i 2 ... jaka będzie średnia ? Tak samo pol na pół
komentarz 7 maja 2016 przez adrian17 Ekspert (344,100 p.)
Ożywiłeś dawny wątek, który już dawno został obgadany do śmierci :/
komentarz 7 maja 2016 przez Artur Wraga Obywatel (1,870 p.)
I ? Nie jest zamknięty
komentarz 8 maja 2016 przez draghan VIP (106,230 p.)
Zamknięcie pytania nie blokuje możliwości komentowania.

A przykład z kulkami w pudełku tylko potwierdza wszystko, co do tej pory tu zostało napisane.

Pozdrawiam.
komentarz 8 maja 2016 przez Sebastian Fojcik Nałogowiec (43,020 p.)
Sprawa już została wyjaśniona w komentarzach powyżej twierdzeniem matematycznym.

Średnia arytmetyczna n liczb losowych przy n dążącym do nieskończoności jest równa połowie przedziału, z którego losujemy.

To znaczy im więcej liczb losowych weźmiemy, tym ich średnia arytmetyczna będzie się zbliżać do połowy.
+2 głosów
odpowiedź 9 grudnia 2015 przez Karol Wiczling Początkujący (430 p.)
Ciekaw jestem w jakim celu jest potrzebna Ci liczba na tyle losowa że te dostarczone w komputerze nie wystarczą?
komentarz 9 grudnia 2015 przez Avernis Nałogowiec (27,400 p.)
Do losowania pozycji przeciwników w sfml, jak dam zwykłe, takie jak w pozadniku pana zelenta, to będą mniej więcej obok siebie
komentarz 10 grudnia 2015 przez Muminek Dyskutant (8,650 p.)
Zrób to w sposób jak najbardziej "losowy" i zwiększający prawdopodobieństwo, że liczby będą jak najbardziej "losowe". Trochę wysiliku szukania w google. Samych losowych nie osiągniesz.
+1 głos
odpowiedź 9 grudnia 2015 przez Benek Szeryf (90,690 p.)
Nie. Chyba, że masz dostęp do komputera kwantowego.
komentarz 9 grudnia 2015 przez Avernis Nałogowiec (27,400 p.)
A jakieś specjalne biblioteki są do tego?
komentarz 9 grudnia 2015 przez ZakosiliMiNeta Nałogowiec (30,910 p.)

A jakieś specjalne biblioteki są do tego?

Mam rozumieć, że dysponujesz komputerem kwantowym ? 

komentarz 10 grudnia 2015 przez Avernis Nałogowiec (27,400 p.)

Przybywam z przyszłości wink

+1 głos
odpowiedź 10 grudnia 2015 przez event15 Szeryf (93,790 p.)
A ja wam polecam świetny materiał Gynvaela:

https://www.youtube.com/watch?v=u43y_WE52Ig

I wszystko będzie jasne ;)
+1 głos
odpowiedź 10 grudnia 2015 przez Schizohatter Nałogowiec (39,600 p.)
Nie dałeś

srand( time( NULL ) );

zgadłem?
0 głosów
odpowiedź 9 grudnia 2015 przez criss Mędrzec (172,590 p.)
A jak to sobie wyobrażasz? :D No nie, nie da się. Na pewno nie w domowych warunkach. W pełni losowe liczby mozna uzyskać z rozkładu jakiegoś tam konkretnego pierwiastka, ale już słabo pamietam o co dokładnie chodziło. Anyway - nie ma szans.
0 głosów
odpowiedź 9 grudnia 2015 przez Radfler VIP (101,030 p.)

Użyj komponentów biblioteki <random>:

std::random_device dev;
std::mt19937 gen(dev()); // Generator

http://en.cppreference.com/w/cpp/header/random

To i tak są liczby pseudolosowe, ale znacznie lepsze.

komentarz 10 grudnia 2015 przez adrian17 Ekspert (344,100 p.)

Eeeeeeee... Czemu?

Konkretniej powinno być "jeśli używasz MinGW". Z tego co wiem, na razie każda wersja std::random_device MinGW nie zwraca liczb losowych (metoda entropy() zwróci 0).

komentarz 10 grudnia 2015 przez niezalogowany
Dokładnie, jeśli ktos jest zainteresowany to zakładałem o tym temat: https://forum.pasja-informatyki.pl/83766/random-generuje-te-same-liczby
komentarz 10 grudnia 2015 przez draghan VIP (106,230 p.)
W MinGW-w64 ten problem nie występuje.
komentarz 10 grudnia 2015 przez adrian17 Ekspert (344,100 p.)
To bardzo dziwne, mam MinGW-w64 4.0.4 z GCC5.2 i występuje. Może w jakiś jeszcze nowszych buildach nie występuje... trudno mi powiedzieć, bo GCC i Clang uparcie zwracają 0 w entropy() nawet, jeśli ich generator jest prawdziwie niedeterministyczny :/
komentarz 10 grudnia 2015 przez draghan VIP (106,230 p.)
Przepraszam, mój błąd. Karygodny wręcz. :) Wypisalem sobie na stdout entropy() i kilka testowych liczb, ale zapomniałem dać znaku rozdzielającego wartość entropy() od pierwszej wylosowanej liczby, w związku z czym uznałem że występuje tam niezerowa wartość.

Teraz odpaliłem sobie ponownie, żeby jeszcze raz sprawdzić - no i dobrze. :) Tak jak napisałem - mea culpa, nawet w jednym z najnowszych (ściągałem w zeszłym tygodniu) MinGW-w64 nie działa to jak należy.

Przepraszam za wprowadzenie w błąd.
0 głosów
odpowiedź 9 grudnia 2015 przez niezalogowany
A co rozumiesz przez liczby losowe?

W informatyce (matematyce) liczby możesz wygenerować w jakiś sposób, co oznacza że nigdy nie będą to liczby w pełni losowe bo stoi za nimi pewne reguła. Losowość jest nieosiągalna dla naszych komputerów.
komentarz 9 grudnia 2015 przez Avernis Nałogowiec (27,400 p.)
No, to. Liczby bardziej losowe miż pseudo losowe
komentarz 9 grudnia 2015 przez niezalogowany
Możesz skorzystać jedynie z lepszych narzędzi, ale nie osiągniesz liczby czysto-losowej

https://www.youtube.com/watch?v=9rIy0xY99a0
0 głosów
odpowiedź 9 grudnia 2015 przez Mikrokontroler xD Stary wyjadacz (13,500 p.)
edycja 9 grudnia 2015 przez Mikrokontroler xD
Pewien doktor opracował generator liczb losowych(w pełni losowych)
na podstawie diod zenera. Generator zaprezentował na swojej habilitacji.

Ale póki co na komputerach możesz tylko pseudolosowe tworzyć.
komentarz 9 grudnia 2015 przez niezalogowany
Diod a nie diód, jestem na elektronice to się nie kłóć ok??
komentarz 9 grudnia 2015 przez Mikrokontroler xD Stary wyjadacz (13,500 p.)
masz rację dzięki :).

ja po elektronice ;)
komentarz 9 grudnia 2015 przez niezalogowany
Więc kolega po fachu :) Grzechy zostały odpuszczone
komentarz 9 grudnia 2015 przez draghan VIP (106,230 p.)
Sprzętowe generatory liczb losowych to żadna nowość. :P

Wystarczy mieć urządzenie, które będzie umiało określić stan pewnych warunków zewnętrznych od niego niezależnych, zamienić to na sygnał elektryczny i ewentualnie przepuścić reprezentację sygnału przez jakiś twister.
0 głosów
odpowiedź 9 grudnia 2015 przez Wiktor Stary wyjadacz (11,120 p.)

Sam nie zagłębiłem się bardziej w temat losowości liczb na komputerach, jednak czytałem ostatnio jakiś artykuł, że bardzo skuteczną losowość można wygenerować poprzez zakres temperatur na każdym rdzeniu i przeprowadzeniu pewnych operacji matematycznych. Można powiedzieć, że dalej jest to pseudolosowość, jednak praktycznie nie do "podrobienia".

Według mnie nie ma takiego czegoś jak pełna "prawdziwa" losowość. Po prostu do wylosowania niektórych liczb jest potrzebne więcej zmiennych niż jesteśmy sobie w stanie wyobrazić, jednak jest to temat na inną dyskusję.smiley

Co o tym sądzicie?

Pozdrawiam.

komentarz 11 grudnia 2015 przez Strategiusz Dyskutant (9,220 p.)
Myślę, że to ciekawe. Ale mierzenie temperatury czy branie liczby z zegara, to wg mnie podobne rzeczy. Można by pewnie też mierzyć ping do jakichś serwerów i też dołożyłoby to jakiś element losowości.
0 głosów
odpowiedź 9 grudnia 2015 przez jegor377 Stary wyjadacz (13,230 p.)
możesz wylosować jakąś liczbę i wylosować miejsce dla przecinka i przecastować do ze stringa do dobule lub floata ;)
0 głosów
odpowiedź 10 grudnia 2015 przez krystian904 Mądrala (6,820 p.)
sam sobie liczby wpisuj to bedzie losowość 100%
komentarz 10 grudnia 2015 przez Avernis Nałogowiec (27,400 p.)
sam sobie odpowiedz na to...
komentarz 10 grudnia 2015 przez Avernis Nałogowiec (27,400 p.)
Przy okacji geniuszu, co jak potrzebuję liczby która będzię się zmieniać co jakiś nie określony czas?
1
komentarz 10 grudnia 2015 przez adrian17 Ekspert (344,100 p.)
komentarz 10 grudnia 2015 przez draghan VIP (106,230 p.)

Hah. laugh adrianyes.

0 głosów
odpowiedź 11 grudnia 2015 przez Marcin Chaciej Nowicjusz (140 p.)
Wygląda na to, że potrzebujesz "std::random_device" (np. zamiast czysto pseudolosowego std::mt19937) po dodaniu #include <random> (C++11). Z tego co się orientuję w procesie tworzenia liczb losowych stara się korzystać z urządzeń zewnętrznych (pobierając informację np. z napięcia na chipsecie, temperatury rdzenia, pamięci itd.), najlepiej działa na Visual Studio Microsoftu, na innych kompilatorach i systemach bywa różnie, w każdym razie można go sprawdzić prosząc o zwrócenie poziomu entropii (kocham to pojęcie) ( random_device::entropy ).

tutaj możesz przeczytać nieco więcej http://www.cplusplus.com/reference/random/random_device/
http://en.cppreference.com/w/cpp/numeric/random/random_device

Jeszcze tutaj ode mnie dwie takie funkcje z którymi praktycznie się nie rozstaję, możesz je zaimplementować do dowolnej klasy, pamiętaj tylko, iż std::random_device jest znacząco wolniejszy od swojego pseudolosowego kuzyna mt19937 (za cenę generowania kryptograficznie bezpiecznych prawdziwie losowych liczb)

#include <random>

std::random_device rgen;

int rnd(int min, int max)
{
    std::uniform_int_distribution<int> uid(min, max);
    return uid(rgen);
}
double rnd(double min, double max)
{
    std::uniform_real_distribution<double> urd(min, max);
    return urd(rgen);
}

Podobne pytania

0 głosów
6 odpowiedzi 396 wizyt
pytanie zadane 19 lipca 2018 w C i C++ przez bubu91 Nowicjusz (160 p.)
+1 głos
1 odpowiedź 565 wizyt
pytanie zadane 25 września 2015 w Inne języki przez niezalogowany
0 głosów
1 odpowiedź 398 wizyt
pytanie zadane 23 września 2020 w C i C++ przez Dezmonths Początkujący (310 p.)

92,451 zapytań

141,261 odpowiedzi

319,073 komentarzy

61,853 pasjonatów

Motyw:

Akcja Pajacyk

Pajacyk od wielu lat dożywia dzieci. Pomóż klikając w zielony brzuszek na stronie. Dziękujemy! ♡

Oto polecana książka warta uwagi.
Pełną listę książek znajdziesz tutaj.

Akademia Sekuraka

Akademia Sekuraka 2024 zapewnia dostęp do minimum 15 szkoleń online z bezpieczeństwa IT oraz dostęp także do materiałów z edycji Sekurak Academy z roku 2023!

Przy zakupie możecie skorzystać z kodu: pasja-akademia - użyjcie go w koszyku, a uzyskacie rabat -30% na bilety w wersji "Standard"! Więcej informacji na temat akademii 2024 znajdziecie tutaj. Dziękujemy ekipie Sekuraka za taką fajną zniżkę dla wszystkich Pasjonatów!

Akademia Sekuraka

Niedawno wystartował dodruk tej świetnej, rozchwytywanej książki (około 940 stron). Mamy dla Was kod: pasja (wpiszcie go w koszyku), dzięki któremu otrzymujemy 10% zniżki - dziękujemy zaprzyjaźnionej ekipie Sekuraka za taki bonus dla Pasjonatów! Książka to pierwszy tom z serii o ITsec, który łagodnie wprowadzi w świat bezpieczeństwa IT każdą osobę - warto, polecamy!

...