Johannes Johannes - 1 month ago 7
Python Question

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?

Answer

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]
Comments