Сначала немного уродливая математика, которую вы уже используете в своем коде.
Определите x и y - биты с вероятностью, равной 1 из X = p (x = 1), Y = p (y = 1) соответственно.
Тогда у нас есть это
p( x & y = 1) = X Y
p( x | y = 1) = 1 - (1-X) (1-Y)
p( x ^ y = 1) = X (1 - Y) + Y (1 - X)
Теперь, если мы допустим Y = 1/2, мы получим
P( x & y ) = X/2
P( x | y ) = (X+1)/2
Теперь установите RHS на желаемую вероятность, и у нас есть два случая, которые мы можем решить для X
X = 2 p // if we use &
X = 2 p - 1 // if we use |
Далее мы предполагаем, что можем использовать это снова, чтобы получить X в терминах другой переменной Z ...
И затем мы продолжаем итерацию, пока не сделаем «достаточно».
Это немного неясно, но рассмотрим р = 0,375
0.375 * 2 = 0.75 < 1.0 so our first operation is &
0.75 * 2 = 1.5 > 1.0 so our second operation is |
0.5 is something we know so we stop.
Таким образом, мы можем получить переменную с p = 0,375 на X1 & (X2 | X3)
Проблема в том, что для большинства переменных это не заканчивается. например,
0.333 *2 = 0.666 < 1.0 so our first operation is &
0.666 *2 = 1.333 > 1.0 so our second operation is |
0.333 *2 = 0.666 < 1.0 so our third operation is &
etc...
, поэтому p = 0,333 можно сгенерировать с помощью
X1 & ( X2 | (X3 & (X4 | ( ... ) ) ) )
Теперь я подозреваю, что использование достаточного количества терминов в серии даст вам достаточно точности, и это можно записать как рекурсивную функцию. Однако, возможно, есть и лучший способ, что это тоже ... Я думаю, что порядок операций связан с двоичным представлением p, я просто не уверен, как именно ... и у меня нет времени думать об этом глубже.
В любом случае, вот какой-то непроверенный код C ++, который делает это. Вы должны быть в состоянии легко javaify это.
uint bitsWithProbability( float p )
{
return bitsWithProbabilityHelper( p, 0.001, 0, 10 );
}
uint bitsWithProbabilityHelper( float p, float tol, int cur_depth, int max_depth )
{
uint X = randbits();
if( cur_depth >= max_depth) return X;
if( p<0.5-tol)
{
return X & bitsWithProbabilityHelper( 2*p, 0.001, cur_depth+1, max_depth );
}
if(p>0.5+tol)
{
return X | bitsWithProbabilityHelper( 2*p-1, 0.001, cur_depth+1, max_depth );
}
return X;
}