random number generation of doubles between two in

2020-07-18 07:15发布

I need to generate X random double numbers uniformly distributed between two intervals [a,b], where a and b are also double numbers.

Those X numbers need to be generated inside of a class function, say myclass::doSomething(a,b). The thing is that the intervals [a,b] passed to the doSomething(a,b) function change each time the doSomething(a,b) function is called by another class function, say doThat().

I would like a solution that allows me to:
1. Have an engine with a higher scope, ideally, it should be seeded only once per application run.
2. The X random double numbers generated inside of each single call to the doSomething() function, should be uniformly distributed.

My solution below does not allow a higher scope for the engine and it seems that the generated numbers are not necessarily uniformly distributed.

//file: utilities.h
template <typename Generator>
double randomDoubleEngine(Generator& engine, double low_bound, double high_bound )
{
        if (low_bound > high_bound){
                std::swap(low_bound, high_bound);
        }

        return std::uniform_real_distribution<>( low_bound, high_bound )( engine );
}

//file: myclass.h
       void myclass::doThat(param1, param2){

            for(int i=0; i < myclass.iter; i++){
                ...
                ...
                doSomething(a,b);
                ...
            }

        }

        void myclass::doSomething(double a, double b)
        {
                std::random_device rd;
                static std::mt19937 engine(rd());
                .....
                double curThreshold = randomDoubleEngine(engine, a, b);
                ...
         }

1条回答
相关推荐>>
2楼-- · 2020-07-18 07:57

I think you want engine to be a static member of myclass. I'm not sure that will make any real difference from what you have, unless you need to use the engine in other methods. I've pasted a possible solution below.

Note also that gcc's looks wrong compared to the standard (see links in code comments), so if you're using that it might explain why whatever test you're applying to these numbers (to check for uniform distribution) is failing. As I understand, gcc wants the engine to return numbers in [0,1), while the standard says it should be uniform integers over some range.

I'm afraid I could only test this with gcc 4.4, since I'm running an older Ubuntu release and ideone doesn't seem to allow std::random_device.

#include <random>
#include <iostream>

/* In GCC 4.4, uniform_real_distribution is called uniform_real; renamed in 4.5
 *
 * However, GCC's description here
 *
 * http://gcc.gnu.org/onlinedocs/libstdc++/libstdc++-api-4.6/a00731.html
 *
 * doesn't match expectation here
 *
 * http://en.cppreference.com/w/cpp/numeric/random/uniform_real_distribution
 *
 * which seems to match 26.5.8.2.2 of N3337
 *
 */
#if defined(__GNUC_MINOR__) && (__GNUC_MINOR__ <= 4)
#  define uniform_real_distribution uniform_real
#endif

template <typename Generator>
double randomDoubleEngine(Generator& engine, double low_bound, double high_bound)
{
  if (low_bound > high_bound){
    std::swap(low_bound, high_bound);
  }
  return std::uniform_real_distribution<double>(low_bound, high_bound)(engine);
}

class myclass
{
  double curThreshold;
  static std::mt19937 engine;
  void doSomething(double a, double b)
  {
    curThreshold= randomDoubleEngine(engine, a, b);
  }
public:
  myclass(): curThreshold(0) {}

  void doThat(){
    doSomething(0,10);
    std::cout << "threshold is " << curThreshold << std::endl;
  }
};

std::mt19937 myclass::engine=std::mt19937(std::random_device()());

int
main()
{
  myclass m;
  m.doThat();
  m.doThat();
  return 0;
}
查看更多
登录 后发表回答