简体   繁体   中英

How to generate random double numbers with high precision in C++?

I am trying to generate a number of series of double random numbers with high precision. For example, 0.856365621 (has 9 digits after decimal).

I've found some methods from inte.net, however, they do generate double random number, but the precision is not as good as I request (only 6 digits after the decimal).

Thus, may I know how to achieve my goal?

In C++11 you can using the <random> header and in this specific example using std::uniform_real_distribution I am able to generate random numbers with more than 6 digits. In order to see set the number of digits that will be printed via std::cout we need to use std::setprecision :

#include <iostream>
#include <random>
#include <iomanip>    

int main()
{
    std::random_device rd;

    std::mt19937 e2(rd());

    std::uniform_real_distribution<> dist(1, 10);

    for( int i = 0 ; i < 10; ++i )
    {
       std::cout << std::fixed << std::setprecision(10) << dist(e2) << std::endl ;
    }

    return 0 ;
}

you can use std::numeric_limits::digits10 to determine the precision available.

std::cout << std::numeric_limits<double>::digits10 << std::endl;

In a typical system, RAND_MAX is 2 31 -1 or something similar to that. So your "precision" from using a method like:L

 double r = rand()/RAND_MAX;

would be 1/(2<sup>31</sup)-1 - this should give you 8-9 digits "precision" in the random number. Make sure you print with high enough precision:

 cout << r << endl;

will not do. This will work better:

 cout << fixed << sprecision(15) << r << endl; 

Of course, there are some systems out there with much smaller RAND_MAX, in which case the results may be less "precise" - however, you should still get digits down in the 9-12 range, just that they are more likely to be "samey".

Why not create your value out of multiple calls of the random function instead?

For instance:

   const int numDecimals = 9;

   double result = 0.0;
   double div = 1.0;
   double mul = 1.0;
   for (int n = 0; n < numDecimals; ++n)
   {
      int t = rand() % 10;
      result += t * mul;
      mul *= 10.0;
      div /= 10.0;
   }    
   result = result * div;

I would personally try a new implementation of the rand function though or at least multiply with the current time or something..

In my case, I'm using MQL5, a very close derivative of C++ for a specific market, whose only random generator produces a random integer from 0 to 32767 (= (2^15)-1). Far too low precision.

So I've adapted his idea -- randomly generate a string of digits any length I want -- to solve my problem, more reliably (and arguably more randomly also), than anything else I can find or think of. My version builds a string and converts it to a double at the end -- avoids any potential math/rounding errors along the way (because we all know 0.1 + 0.2.= 0.3 )

Posting it here in case it helps anyone.

(Disclaimer: The following is valid MQL5. MQL5 and C++ are very close, but some differences. eg. No RAND_MAX constant (so I've hard-coded the 32767). I'm not entirely sure of all the differences, so there may be C++ syntax errors here. Please adapt accordingly).

const int RAND_MAX_INCL = 32767;
const int RAND_MAX_EXCL = RAND_MAX_INCL + 1;

int iRandomDigit() {
    const double dRand = rand()/RAND_MAX_EXCL;  // double 0.0 <= dRand < 1.0
    return (int)(dRand * 10); // int 0 <= result < 10
};

double dRandom0IncTo1Exc(const int iPrecisionDigits) {
    int iPrecisionDigits2 = iPrecisionDigits;
    if ( iPrecisionDigits > DBL_DIG ) { // DBL_DIG == "Number of significant decimal digits for double type"
        Print("WARNING: Can't generate random number with precision > ", DBL_DIG, ". Adjusted precision to ", DBL_DIG, " accordingly.");
        iPrecisionDigits2 = DBL_DIG;
    };
    string sDigits = "";
    for (int i = 0; i < iPrecisionDigits2; i++) {
        sDigits += (string)iRandomDigit();
    };
    const string sResult = "0." + sDigits;
    const double dResult = StringToDouble(sResult);
    return dResult;
}

Noted in a comment on @MasterPlanMan's answer -- the other answers use more "official" methods designed for the question, from standard library, etc. However, I think conceptually it's a good solution when faced with limitations that the other answers can't address.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM