There's a better way to do this, you use inverse CDF to avoid all the RNG calls.
Generate a random number, then skip items until you reach that number:
selectRandomFromIteratorOptimized(iterator) { if (!iterator.moveNext()) { return null; }
var winner = iterator.current();
var count = 1;
while (true) {
var u = random_float_open(0.0, 1.0);
var skip = (int)Math.Floor(Math.Log(u) / Math.Log(1.0 - (1.0 / (count + 1))));
for (var i = 0; i < skip; ++i) {
if (!iterator.moveNext()) {
return winner;
}
++count;
}
if (!iterator.moveNext()) {
return winner;
}
++count;
winner = iterator.current();
}
}