Я пишу алгоритм Монте-Карло, в котором в какой-то момент мне нужно разделить случайную величину. Точнее: случайная величина используется в качестве ширины шага для разностного отношения, поэтому я фактически сначала умножаю что-то на переменную, а затем снова делю ее на некоторую локально линейную функцию этого выражения. Как
double f(double);
std::tr1::variate_generator<std::tr1::mt19937, std::tr1::normal_distribution<> >
r( std::tr1::mt19937(time(NULL)),
std::tr1::normal_distribution<>(0) );
double h = r();
double a = ( f(x+h) - f(x) ) / h;
Это прекрасно работает большую часть времени, но не работает, когда h=0
. Математически, это не проблема, потому что при любом конечном (или даже счетном) выборе нормально распределенных случайных величин все они будут отличны от нуля с вероятностью 1. Но в цифровой реализации я столкнусь с h==0
каждые ≈ Вызовы функций 2³² (независимо от того, имеет ли мерсенновый твистер период больше, чем вселенная, он все равно выдает обычные long
с!).
Довольно просто избежать этой проблемы, в данный момент я делаю
double h = r();
while (h==0) h=r();
но я не считаю это особенно элегантным. Есть ли лучший способ?
Функция, которую я оцениваю, на самом деле не просто ℝ-> ℝ, как
f
, а ℝᵐxℝⁿ -> which, в которой я вычисляю градиент по ℝᵐ переменным, в то же время численно интегрируя по ℝⁿ переменным. Вся функция наложена на непредсказуемый (но «когерентный») шум, иногда с определенными (но неизвестными) выдающимися частотами, вот что доставляет мне неприятности, когда я пробую его с фиксированными значениями для
h
.