„numer ten powinien wyglądać następująco: xxxxx, yyyyy”. Jak generować losowe liczby podwójne i jak formatować jedynki jako ciągi, to zupełnie odrębne kwestie.
Steve Jessop
I pomyśl o tym alternatywnie: generowanie równo rozłożonych podwójnych i generowanie równomiernie rozłożonych liczb dziesiętnych to nieco inne, choć powiązane, zadania.
Steve Jessop
Generowanie liczb całkowitych o równomiernym rozkładzie jest ściślej związane z problemem ułamków dziesiętnych.
Potatoswatter
Odpowiedzi:
116
Oto jak
doublefRand(double fMin, double fMax){
double f = (double)rand() / RAND_MAX;
return fMin + f * (fMax - fMin);
}
Pamiętaj, aby wywołać srand () z odpowiednim ziarnem za każdym razem, gdy program zostanie uruchomiony.
[Edytuj] Ta odpowiedź jest przestarzała, ponieważ C ++ ma swoją natywną, losową bibliotekę nie opartą na C (zobacz odpowiedź Alessandro Jacopsona) Ale to nadal dotyczy C
Jeśli dodasz 1 do RAND_MAX, zrób to ostrożnie, ponieważ może być równe INT_MAX. double f = rand() / (RAND_MAX + 1.0);
Steve Jessop
8
Zauważ, że losowość tego może być ograniczona. Zakres xxxxx, yyyyy sugeruje 10 cyfr dziesiętnych. Istnieje wiele systemów, w których RAND_MAX jest mniejszy niż 10 ^ 10. Oznaczałoby to, że niektóre liczby z tego zakresu mająp(xxxxx,yyyyy)==0.0
MSalters
7
Jeśli to możliwe, powinieneś unikać rand (). Zobacz inną odpowiedź dla rozwiązania C ++ 11 lub TR1.
jfritz42,
Nie wszyscy używają C ++ 0x, tr1 lub C ++ 11 Czy jest jakieś odniesienie, które pokazuje, że rand () należy unikać? To był jedyny sposób na uzyskanie liczb losowych od dziesięcioleci.
Jeśli dokładność jest tutaj problemem, możesz utworzyć liczby losowe z dokładniejszą podziałką, losując znaczące bity. Załóżmy, że chcemy mieć podwójną wartość między 0,0 a 1000,0.
Na przykład na MSVC (12 / Win32) RAND_MAX to 32767.
Jeśli użyjesz wspólnego rand()/RAND_MAXschematu, twoje luki będą tak duże jak
1.0 / 32767.0 * ( 1000.0 - 0.0) = 0.0305 ...
W przypadku podwójnych zmiennych IEE 754 (53 znaczące bity) i 53-bitowej randomizacji najmniejsza możliwa luka randomizacji dla problemu od 0 do 1000 będzie wynosić
2^-53 * (1000.0 - 0.0) = 1.110e-13
a zatem znacznie niższe.
Wadą jest to, że do uzyskania losowej liczby całkowitej (przy założeniu 15-bitowego RNG) potrzebne będą 4 wywołania rand ().
Uwaga: nie wiem, czy liczba bitów dla długości bez znaku (64 bity) jest większa niż liczba bitów podwójnej mantysy (53 bity dla IEE 754) na wszystkich platformach, czy nie. Byłoby prawdopodobnie „sprytne” dołączenie czeku, takiego jak if (sizeof(unsigned long long)*8 > num_mant_bits) ...gdyby tak nie było.
Odpowiedzi:
Oto jak
double fRand(double fMin, double fMax) { double f = (double)rand() / RAND_MAX; return fMin + f * (fMax - fMin); }
Pamiętaj, aby wywołać srand () z odpowiednim ziarnem za każdym razem, gdy program zostanie uruchomiony.
[Edytuj] Ta odpowiedź jest przestarzała, ponieważ C ++ ma swoją natywną, losową bibliotekę nie opartą na C (zobacz odpowiedź Alessandro Jacopsona) Ale to nadal dotyczy C
źródło
double f = rand() / (RAND_MAX + 1.0);
p(xxxxx,yyyyy)==0.0
To rozwiązanie wymaga C ++ 11 (lub TR1).
#include <random> int main() { double lower_bound = 0; double upper_bound = 10000; std::uniform_real_distribution<double> unif(lower_bound,upper_bound); std::default_random_engine re; double a_random_double = unif(re); return 0; }
Aby uzyskać więcej informacji, zobacz artykuł Johna D. Cooka „Generowanie liczb losowych przy użyciu C ++ TR1” .
Zobacz także „Generowanie liczb losowych” Stroustrupa .
źródło
Powinno to być wydajne, bezpieczne dla wątków i wystarczająco elastyczne do wielu zastosowań:
#include <random> #include <iostream> template<typename Numeric, typename Generator = std::mt19937> Numeric random(Numeric from, Numeric to) { thread_local static Generator gen(std::random_device{}()); using dist_type = typename std::conditional < std::is_integral<Numeric>::value , std::uniform_int_distribution<Numeric> , std::uniform_real_distribution<Numeric> >::type; thread_local static dist_type dist; return dist(gen, typename dist_type::param_type{from, to}); } int main(int, char*[]) { for(auto i = 0U; i < 20; ++i) std::cout << random<double>(0.0, 0.3) << '\n'; }
źródło
Jeśli dokładność jest tutaj problemem, możesz utworzyć liczby losowe z dokładniejszą podziałką, losując znaczące bity. Załóżmy, że chcemy mieć podwójną wartość między 0,0 a 1000,0.
Na przykład na MSVC (12 / Win32) RAND_MAX to 32767.
Jeśli użyjesz wspólnego
rand()/RAND_MAX
schematu, twoje luki będą tak duże jak1.0 / 32767.0 * ( 1000.0 - 0.0) = 0.0305 ...
W przypadku podwójnych zmiennych IEE 754 (53 znaczące bity) i 53-bitowej randomizacji najmniejsza możliwa luka randomizacji dla problemu od 0 do 1000 będzie wynosić
2^-53 * (1000.0 - 0.0) = 1.110e-13
a zatem znacznie niższe.
Wadą jest to, że do uzyskania losowej liczby całkowitej (przy założeniu 15-bitowego RNG) potrzebne będą 4 wywołania rand ().
double random_range (double const range_min, double const range_max) { static unsigned long long const mant_mask53(9007199254740991); static double const i_to_d53(1.0/9007199254740992.0); unsigned long long const r( (unsigned long long(rand()) | (unsigned long long(rand()) << 15) | (unsigned long long(rand()) << 30) | (unsigned long long(rand()) << 45)) & mant_mask53 ); return range_min + i_to_d53*double(r)*(range_max-range_min); }
Jeśli liczba bitów mantysy lub RNG jest nieznana, w ramach funkcji należy uzyskać odpowiednie wartości.
#include <limits> using namespace std; double random_range_p (double const range_min, double const range_max) { static unsigned long long const num_mant_bits(numeric_limits<double>::digits), ll_one(1), mant_limit(ll_one << num_mant_bits); static double const i_to_d(1.0/double(mant_limit)); static size_t num_rand_calls, rng_bits; if (num_rand_calls == 0 || rng_bits == 0) { size_t const rand_max(RAND_MAX), one(1); while (rand_max > (one << rng_bits)) { ++rng_bits; } num_rand_calls = size_t(ceil(double(num_mant_bits)/double(rng_bits))); } unsigned long long r(0); for (size_t i=0; i<num_rand_calls; ++i) { r |= (unsigned long long(rand()) << (i*rng_bits)); } r = r & (mant_limit-ll_one); return range_min + i_to_d*double(r)*(range_max-range_min); }
Uwaga: nie wiem, czy liczba bitów dla długości bez znaku (64 bity) jest większa niż liczba bitów podwójnej mantysy (53 bity dla IEE 754) na wszystkich platformach, czy nie. Byłoby prawdopodobnie „sprytne” dołączenie czeku, takiego jak
if (sizeof(unsigned long long)*8 > num_mant_bits) ...
gdyby tak nie było.źródło
Ten fragment pochodzi bezpośrednio z książki Stroustrup The C ++ Programming Language (4. wydanie) , §40.7; wymaga C ++ 11:
#include <functional> #include <random> class Rand_double { public: Rand_double(double low, double high) :r(std::bind(std::uniform_real_distribution<>(low,high),std::default_random_engine())){} double operator()(){ return r(); } private: std::function<double()> r; }; #include <iostream> int main() { // create the random number generator: Rand_double rd{0,0.5}; // print 10 random number between 0 and 0.5 for (int i=0;i<10;++i){ std::cout << rd() << ' '; } return 0; }
źródło
coś takiego:
#include <iostream> #include <time.h> using namespace std; int main() { const long max_rand = 1000000L; double x1 = 12.33, x2 = 34.123, x; srandom(time(NULL)); x = x1 + ( x2 - x1) * (random() % max_rand) / max_rand; cout << x1 << " <= " << x << " <= " << x2 << endl; return 0; }
źródło