random number generation of doubles between two intervals [a,b]

余生颓废 提交于 2019-12-06 04:44:52

问题


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:


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


来源:https://stackoverflow.com/questions/10044324/random-number-generation-of-doubles-between-two-intervals-a-b

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!