这里要注意一点——我在实现这个时遇到了一个很大的问题。似乎如果 max()/min()/operator() 的返回类型不是 64 位,那么分布将重新采样。我的(无符号)32 位 Sobol 实现对每个偏差进行两次采样,从而破坏了数字的属性。此代码重现:
#include <random>
#include <limits>
#include <iostream>
#include <cstdint>
typedef uint32_t rng_int_t;
int requested = 0;
int sampled = 0;
struct Quasi
{
rng_int_t operator()()
{
++sampled;
return 0;
}
rng_int_t min() const
{
return 0;
}
rng_int_t max() const
{
return std::numeric_limits<rng_int_t>::max();
}
};
int main()
{
std::uniform_real_distribution<double> dist(0.0,1.0);
Quasi q;
double total = 0.0;
for (size_t i = 0; i < 10; ++i)
{
dist(q);
++requested;
}
std::cout << "requested: " << requested << std::endl;
std::cout << "sampled: " << sampled << std::endl;
}
输出(使用 g++ 5.4):
requested: 10
sampled: 20
甚至在使用 -m32 编译时。如果您将 rng_int_t 更改为 64 位,问题就会消失。我的解决方法是将 32 位值粘贴到返回值的最高有效位中,例如
return uint64_t(val) << 32;