pythonintegerprobabilityrounding

Random rounding to integer in Python


I am looking for a way to round a floating point number up or down to the next integer based on a probability derived from the numbers after the decimal point. For example the floating number 6.1 can be rounded to 6 and to 7. The probability for beeing rounded to 7 is 0.1 and the probability to be rounded to 6 is 1-0.1. So if I run this rounding experiment infinite times, the average of all integer results should be 6.1 again. I don't know if there is a name for such a procedure and if there is already and implemented function in Python. Of course it'd be very nice if it is possible to round also to e.g. 2 decimal places the same way.

Does that make sense? Any ideas?


Solution

  • The probability you're looking for is x-int(x).

    To sample with this probability, do random.random() < x-int(x)

    import random
    import math
    import numpy as np
    
    def prob_round(x):
        sign = np.sign(x)
        x = abs(x)
        is_up = random.random() < x-int(x)
        round_func = math.ceil if is_up else math.floor
        return sign * round_func(x)
    
    x = 6.1
    sum( prob_round(x) for i in range(100) ) / 100.
    => 6.12
    

    EDIT: adding an optional prec argument:

    def prob_round(x, prec = 0):
        fixup = np.sign(x) * 10**prec
        x *= fixup
        is_up = random.random() < x-int(x)
        round_func = math.ceil if is_up else math.floor
        return round_func(x) / fixup
    
    x = 8.33333333
    [ prob_round(x, prec = 2) for i in range(10) ]
    => [8.3399999999999999,
     8.3300000000000001,
     8.3399999999999999,
     8.3300000000000001,
     8.3300000000000001,
     8.3300000000000001,
     8.3300000000000001,
     8.3300000000000001,
     8.3399999999999999,
     8.3399999999999999]