pythonrandom-walkcoin-flipping

Random walk between 0 and 1 generating only 0 for cases lower than 0.5 as input


I am trying to write a function that takes a float between 0 and 1 (including 0 and 1) it then calculates the distances from both 0 and 1 and takes the minimum between the two to be the amount that it would walk.

The direction of movement is then decided by a fair coin toss. If the result is heads (1) the movement amount will be added to the input float. If the result is tails (0) the movement amount will be subtracted from the input float. This will be repeated until the input float reaches either 0 or 1.

If the float becomes 1 then a counter called 'Success' is incremented. The entire process is repeated a set number of times and the finally the function returns 'Success' divided by the number of itterations to get a probability of the input float resulting in a 1.

I then divide the range 0 to 1 into 1024 evenly spaced points. Each of these is then given to the function and the inputs and outputs are stored. This is then plot with Seaborn with the input being on the X-axis and the output on the Y-axis.

I expected this to produce a line that roughly follows y = x since that is statistically what should happen. Instead I get this: Probability of Success vs X_Start with 1024 points.

This is my code:

from random import random, choice
import seaborn as sns
import pandas as pd
import matplotlib.pyplot as plt
import gc

def Experiment(X_Start) -> float:
    Num_Trials = 1000
    Success = 0

    for Trial in range(Num_Trials):
        X_Current = X_Star
        Movement_Radius = min(X_Start, 1 - X_Start)

        while 0 < X_Current < 1:
            if choice([0, 1]):
                X_Current += Movement_Radius
            else:
                X_Current -= Movement_Radius

        if X_Current == 1:
            Success += 1

    return Success / Num_Trials, X_Start

if __name__ == '__main__':
    results = {'X_Start': [], 'Probability': []}
    n = 5

    for i in range(0, 2**n+1):
        Probability, X_Initial = Experiment(i/2**n)
        results['X_Start'].append(X_Initial)
        results['Probability'].append(Probability)
    
    df = pd.DataFrame(results)

    plt.figure(figsize=(12,8))
    sns.scatterplot(data=df, x='X_Start', y='Probability', marker='x', color='red')
    plt.xlabel('X_Start')
    plt.ylabel('Probability of Success')
    plt.title(f'Probability of Success vs X_Start with {2**n} points')
    plt.show()
    plt.close()

I am not sure why this is happening.


Solution

  • Floating point number are imprecise. Comparing floats with == will give unexpected results quite often. In your case, you will (almost) never hit exactly 1.

    Try something like if X_Current >= 1: to test for success.