1

I am trying to get a random number generator that will be biased in that it takes a number, and prints a number that is likely to be close. Here's what I have now:

def biasedRandom(rangen, rangex, target, biaslevel=1):
    if rangen > rangex:
        raise ValueError("Min value is less than max value.")
        return
    if not target in range(rangen, rangex):
        raise ValueError("Bias target not inside range of random.")
        return

    num = random.randint(rangen, rangex)
    for i in range(biaslevel):
        distance = abs(num - target)
        num -= random.randint(0, distance)

    return num

This works pretty well, however it has on occasion given completely outrageous numbers; e.g. it once gave -246174068358 for (1,100,30,60). I figure there is just a bug in there that I am not seeing.

Thanks in advance.

winwaed
  • 7,645
  • 6
  • 36
  • 81
Violet
  • 507
  • 4
  • 15
  • 1
    wouldn't you want to add to `num` if it's less than `target` instead of always subtracting? say you got 1 the first time, then if you subtract from it 60 more times, that result isn't so outrageous anymore. – jswolf19 Feb 13 '11 at 03:02
  • 2
    BTW: there's no need for a `return` after a `raise`: it will never be reached. – Ned Batchelder Feb 13 '11 at 03:04
  • that must be it, I was still thinking about differences, where you always subtract. – Violet Feb 13 '11 at 03:05

2 Answers2

4

raise exits the function - you do not need to follow raise with return

target in range(lo, hi) is inefficient; why not lo <= target < hi?

Edit:

import random
def biasedRandom(lo, hi, target, steps=1):
    if lo >= hi:
        raise ValueError("lo should be less than hi")
    elif target < lo or target >= hi:
        raise ValueError("target not in range(lo, hi)")
    else:
        num = random.randint(lo, hi)
        for i in range(steps):
            num += int(random.random() * (target - num))
        return num

As steps is increased, this will pretty rapidly converge on target; you might want to do some trial distributions to make sure that you are getting what you expected, or try using random.gauss instead.

Hugh Bothwell
  • 55,315
  • 8
  • 84
  • 99
  • I like this solution; Very clean. – Violet Feb 13 '11 at 03:19
  • 1
    My quick test just now showed that while it quickly approaches the target, it will never actually meet it. I tried it using `round()` instead of `int()` in the loop, and that seemed to work better. – Violet Feb 13 '11 at 03:31
0

In the last line for calculating num, were you thinking something like this?

    num = abs(num - random.randint(0,distance))
Senthil Kumaran
  • 54,681
  • 14
  • 94
  • 131
  • I don't think that's quite it. That may have been what my subconscious thought I was doing when I wrote it, but I think the real answer lies in weather `num < target` – Violet Feb 13 '11 at 03:12