From: Stefano Crocco Date: 2009-09-25T15:34:32+09:00 Subject: Re: Roulette & rand On Friday 25 September 2009, Semih Ozkoseoglu wrote: > |Hi, > | > |I'm trying to teach my self ruby so i decided to write a simple roulette > |that picks a rand number (0 to 36) then decides if its red or black. but > |after i've written a version of the code i realized that the code was > |biased towards black ( much easier to see over 1 million rolls) > | > |Then to test this I've simplified everything and its still biased > |against black. if i take 0 out of the equation and made use (1+rand(25)) > |the bias disappeared. > | > |Anyway without further annoying you here is the code. If you spin it for > |over a million you can easily see the bias (i tried up to 1000000000). > | > |Thanks for any help. I know it's not a life or death situation but for > |the life of me I just want to know why is this happening. > | > |THE CODE: > | > |# ARRAYS ======================= > | > |black = [2, 4, 6, 8, 10, 11, 13, 15, 17, 20, 22, 24, 26, 28, 29, 31, 33, > |35] > |red = [1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34, > |36] > |zero = [0] > | > |# VARIABLES =================== > | > |bl = 0 > |rd = 0 > |zr = 0 > | > |# # OF ROLLS ================== > | > |puts 'How many rolls to simulate' > |number_of_rolls = gets.chomp.to_i > | > |# THE LOOP ==================== > | > |while number_of_rolls > 0 > | > | > | number = rand(36) > | > | if > | black.include?(number) > | bl +=1 > | elsif > | red.include?(number) > | rd +=1 > | elsif > | zero.include?(number) > | zr +=1 > | end > | number_of_rolls -=1 > |end > | > |puts bl > |puts rd > |puts zr I think the problem comes from the fact that rand(n) returns an integer between 0 and n-1. In your case, this means that the number 36 will never be generated, which in turn implies that there are more black numbers (18) than red (17 since 36 will never be generated). To avoid this, you'll need to replace rand(36) with rand(37), which generates numbers between 0 and 36. By the way, you can greatly simplify your code, like this: colors = {} [2, 4, 6, 8, 10, 11, 13, 15, 17, 20, 22, 24, 26, 28, 29, 31,33,35].each do |i| colors[i] = :black end [1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32,34,36].each do |i| colors[i] = :red end colors[0] = :zero results = {:black => 0, :red => 0, :zero => 0} puts 'How many rolls to simulate' number_of_rolls = gets.chomp.to_i number_of_rolls.times do number = rand(37) color = colors[number] results[color] += 1 end puts "Black: #{results[:black]}" puts "Red: #{results[:red]}" puts "Zero: #{results[:zero]}" What this code does is the following: * create a hash (called colors) which associates each number with its color, represented by a symbol. The hash is filled from arrays containing the black numbers and the red ones (it could also be filled by hand: colors[1] = :red colors[2] = :black ... * create the hash results which will contain the number of times each color is choosen. Therefore, the hash contains three entries, :black, :red and :zero, all set to 0 * let the user choose the number of rolls * for the number of times chosen by the user, do the following - generate a random number between 0 and 36 - get the color corresponding to the number. This is done by looking at the value corresponding to the number in the colors hash - increase by one the result relative to the chosen color * displays the result I hope this helps Stefano