c++11随机数生成:如何在没有模板的情况下用' mt19937 '重新实现' uniform_int_distr
c++11 random number generation: how to re-implement `uniform_int_distribution` with `mt19937` without templates
我正在尝试重新实现没有模板的c++11 uniform_int_distribution
,特别是mt19937
,因为我想将这个典型用例中的功能移植到没有模板设施的其他语言中,如果有一个更可读的版本就太好了。阅读gcc实现的难度远远超出了我对从一种均匀分布到另一种均匀分布的简单数学转换的预期。(是的,我知道这是专门化的,我不会从这个实践中获得新的功能)
我查看了gcc 4.8.1头文件。最常用的mt19937
类是typedef:
typedef mersenne_twister_engine<
uint_fast32_t,
32, 624, 397, 31,
0x9908b0dfUL, 11,
0xffffffffUL, 7,
0x9d2c5680UL, 15,
0xefc60000UL, 18, 1812433253UL> mt19937;
gcc中uniform_int_distribution
的代码是大量模板化的,对我来说不是很好读。我想知道如何简化/专门化该代码为非模板代码,只是为了mt19937
的情况。
我从4.8.1/include/c++/bits/random找到的最相关的代码。tcc附加在末尾(为了清晰起见,删除了双下划线__
)。
我试图专门化代码,但不是很成功。对于初学者,我试图找出mt19937的范围:最小值为0,最大值为(在random.h中):
static constexpr result_type
max()
{ return __detail::_Shift<_UIntType, __w>::__value - 1; }
,它涉及复杂的模板编程,不容易阅读。我想也许直接问总比逆向工程模板好。
我的问题是:
- 特定型号mt19937的范围(最大值)是多少?
- 如何使用特定于
uint32
和mt19973
的类型和值专门化其余代码。
提前感谢。
——GCC 4.8.1从mt19937到uniform_int_distribution的抽样代码——
template<typename _IntType>
template<typename _ForwardIterator,
typename _UniformRandomNumberGenerator>
void
uniform_int_distribution<_IntType>::
generate_impl(_ForwardIterator f, _ForwardIterator t,
_UniformRandomNumberGenerator& urng,
const param_type& param)
{
glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>)
typedef typename _UniformRandomNumberGenerator::result_type
_Gresult_type;
typedef typename std::make_unsigned<result_type>::type utype;
typedef typename std::common_type<_Gresult_type, utype>::type
uctype;
const uctype urngmin = urng.min();
const uctype urngmax = urng.max();
const uctype urngrange = urngmax - urngmin;
const uctype urange
= uctype(param.b()) - uctype(param.a());
uctype ret;
if (urngrange > urange)
{
if (detail::_Power_of_2(urngrange + 1)
&& detail::_Power_of_2(urange + 1))
{
while (f != t)
{
ret = uctype(urng()) - urngmin;
*f++ = (ret & urange) + param.a();
}
}
else
{
// downscaling
const uctype uerange = urange + 1; // urange can be zero
const uctype scaling = urngrange / uerange;
const uctype past = uerange * scaling;
while (f != t)
{
do
ret = uctype(urng()) - urngmin;
while (ret >= past);
*f++ = ret / scaling + param.a();
}
}
}
else if (urngrange < urange)
{
// upscaling
/*
Note that every value in [0, urange]
can be written uniquely as
(urngrange + 1) * high + low
where
high in [0, urange / (urngrange + 1)]
and
low in [0, urngrange].
*/
uctype tmp; // wraparound control
while (f != t)
{
do
{
const uctype uerngrange = urngrange + 1;
tmp = (uerngrange * operator()
(urng, param_type(0, urange / uerngrange)));
ret = tmp + (uctype(urng()) - urngmin);
}
while (ret > urange || ret < tmp);
*f++ = ret;
}
}
else
while (f != t)
*f++ = uctype(urng()) - urngmin + param.a();
}
-
mt19937生成整数[0,2^32-1]:
std::mt19937 mt_gen; std::cout << mt_gen.min() << 'n'; std::cout << mt_gen.max() << 'n';
为
0
4294967295
2。如果我理解正确的话,您想"手工"专门化模板,但没有弄清楚uniform_int_distribution到底是做什么的?一旦有了mt19937(例如http://www.math.sci.hiroshima-u.ac.jp/~m-mat/MT/MT2002/CODES/mt19937ar.c),在给定的[low, high]范围内生成均匀分布的整数在概念上很简单,但是有一些细节需要注意(例如,仔细检查偏离1的错误)。这里的第二个答案是在C中生成整数的统一分布(在可接受的分布之后)可能会有帮助。
- 有没有比在库中添加一个并非由所有派生类实现的新虚拟函数更好的设计实践
- C++ 如何使用动态计算的新节点实现 A*?
- 实现一个函数,该函数将字符串作为输入并返回一个新字符串,辅音字母不替换为 "!"
- 为什么这个新的 [ ] 和删除 [ ] 实现会分解为 12 >整数?
- 在不创建新节点的情况下实现带有映射的trie
- 使用 Qt5 的新信号/插槽实现向滑块发出信号
- 如何实现由TPAINTBOX创建的新组件的OnMousedown,OnMouseUp事件
- 为什么我不能使私人运营商成为新的并使用默认实现?
- 如何向 C++ 中无法访问其实现的类添加新函数
- 在哪里可以找到C 中新运营商的确切实现
- C++新的不同实现
- 如何实现一个创建新对象并返回对它的引用的C++方法
- 如何实现消费者生产者,消费者可以请求新的数据
- 如何实现C++"新"运算符
- 我可以在不使用新关键字的情况下以某种方式实现这一点吗?C++
- 如何实现一个简单的容器放置新和放置功能
- 您将如何重构这种多态设计,以便在添加新实现时使其更加灵活?
- 为什么不使用模板实现新内容?
- 新的std::string实现(gcc 5.1)
- 库函数的新实现,并在其中调用旧实现