Generieren Sie zufällige Doppelzahlen in c ++

80

Wie man in c ++ Zufallszahlen zwischen zwei Doppelwerten generiert, sollten diese Zahlen wie xxxxx, yyyyy aussehen.

Radi
quelle
6
"Diese Nummer sollte wie xxxxx aussehen, yyyyy". Das Generieren von zufälligen Doubles und das Formatieren von Doubles als Zeichenfolgen sind völlig separate Themen.
Steve Jessop
Und denken Sie alternativ darüber nach: Das Erzeugen gleichmäßig verteilter Doubles und das Erzeugen gleichmäßig verteilter Dezimalstellen sind etwas andere, wenn auch verwandte Aufgaben.
Steve Jessop
Das Erzeugen gleichmäßig verteilter Ganzzahlen hängt enger mit dem Dezimalstellenproblem zusammen.
Potatoswatter

Antworten:

115

Hier ist wie

double fRand(double fMin, double fMax)
{
    double f = (double)rand() / RAND_MAX;
    return fMin + f * (fMax - fMin);
}

Denken Sie daran, srand () bei jedem Programmstart mit einem geeigneten Startwert aufzurufen.

[Bearbeiten] Diese Antwort ist veraltet, da C ++ eine native, nicht C-basierte Zufallsbibliothek hat (siehe Antwort von Alessandro Jacopsons). Dies gilt jedoch weiterhin für C.

rep_movsd
quelle
10
Wenn Sie 1 zu RAND_MAX hinzufügen, gehen Sie vorsichtig vor, da dies möglicherweise gleich INT_MAX ist. double f = rand() / (RAND_MAX + 1.0);
Steve Jessop
8
Beachten Sie, dass die Zufälligkeit davon begrenzt sein kann. Der Bereich xxxxx, yyyyy schlägt 10 Dezimalstellen vor. Es gibt viele Systeme, in denen RAND_MAX kleiner als 10 ^ 10 ist. Dies würde bedeuten, dass einige Zahlen in diesem Bereich habenp(xxxxx,yyyyy)==0.0
MSalters
7
Sie sollten rand () nach Möglichkeit vermeiden. In der anderen Antwort finden Sie eine C ++ 11- oder TR1-Lösung.
jfritz42
Nicht jeder verwendet C ++ 0x, tr1 oder C ++ 11. Gibt es eine Referenz, die zeigt, dass rand () vermieden werden sollte? Es ist seit Jahrzehnten der einzige Weg, Zufallszahlen zu erhalten.
rep_movsd
1
@ChamilaWijayarathna, Sie müssen cstdlib
Veridian
98

Diese Lösung erfordert C ++ 11 (oder 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;
}

Weitere Informationen finden Sie in John D. Cooks "Zufallszahlengenerierung mit C ++ TR1" .

Siehe auch Stroustrups "Zufallszahlengenerierung" .

Alessandro Jacopson
quelle
7
Vielleicht möchten Sie dies mit einem neueren cppreference- Dokument aktualisieren , was ziemlich gut ist.
Shafik Yaghmour
9

Dies sollte performant, threadsicher und flexibel genug für viele Anwendungen sein:

#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';
}
Galik
quelle
7

Wenn hier die Genauigkeit eine Rolle spielt, können Sie Zufallszahlen mit einer feineren Teilung erstellen, indem Sie die signifikanten Bits randomisieren. Nehmen wir an, wir wollen ein Double zwischen 0.0 und 1000.0.

Unter MSVC (12 / Win32) ist RAND_MAX beispielsweise 32767.

Wenn Sie das gemeinsame rand()/RAND_MAXSchema verwenden, sind Ihre Lücken so groß wie

1.0 / 32767.0 * ( 1000.0 - 0.0) = 0.0305 ...

Im Fall von IEE 754-Doppelvariablen (53 signifikante Bits) und 53-Bit-Randomisierung ist die kleinstmögliche Randomisierungslücke für das 0 bis 1000-Problem

2^-53 * (1000.0 - 0.0) = 1.110e-13

und daher deutlich niedriger.

Der Nachteil ist, dass 4 rand () -Aufrufe erforderlich sind, um die zufällige Integralnummer zu erhalten (unter der Annahme eines 15-Bit-RNG).

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

Wenn die Anzahl der Bits für die Mantisse oder das RNG unbekannt ist, müssen die entsprechenden Werte innerhalb der Funktion erhalten werden.

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

Hinweis: Ich weiß nicht, ob die Anzahl der Bits für Long Long ohne Vorzeichen (64 Bit) größer ist als die Anzahl der Bits mit doppelter Mantisse (53 Bit für IEE 754) auf allen Plattformen oder nicht. Es wäre wahrscheinlich "klug", einen Scheck einzuschließen, if (sizeof(unsigned long long)*8 > num_mant_bits) ...wenn dies nicht der Fall ist.

Pixelchemist
quelle
3

Dieses Snippet stammt direkt aus Stroustrups The C ++ Programming Language (4. Ausgabe) , §40.7; es erfordert 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;
}
Alessandro Jacopson
quelle
0

etwas wie das:

#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;
}
Oleg Razgulyaev
quelle
2
"(random ()% max_rand)" = "random ()" (dh 3% 7 = 3). Dies wäre ein verschwendeter Verarbeitungsschritt.
Zak