Search code examples
randomfunctional-programmingbluegiga

Getting a number to show up a certain percent of a time


I'm looking to build a code to make a number show up 50% of the time, 35% of the time and 15% of the time. I'm quite new to BGscript but I haven't had much luck making this reliable or work at all. Even if you haven't done any BGscript but have done this in an other language. That would be really great!


Solution

  • I've written a blog post and example code for generating a random unsigned int in BGScript here: http://www.sureshjoshi.com/embedded/bgscript-random-number-generator/

    Essentially, it uses a xorshift seeded by the module's serial number and/or the ADCs LSB noise to generate a pseudo-random number.

    # Perform a xorshift (https://en.wikipedia.org/wiki/Xorshift) to generate a pseudo-random number
    export procedure rand()
        t = x ^ (x << 11)
        x = y
        y = z 
        z = rand_number
        rand_number = rand_number ^ (rand_number >> 19) ^ t ^ (t >> 8)
    end
    

    and initialized here:

    # Get local BT address
    call system_address_get()(mac_addr(0:6))
    ...
    tmp(15:1) = (mac_addr(0:1)/$10)+ 48 + ((mac_addr(0:1)/$10)/10*7)
    tmp(16:1) = (mac_addr(0:1)&$f) + 48 + ((mac_addr(0:1)&$f )/10*7)
    ...
    # Seed the random number generator using the last digits of the serial number 
    seed = (tmp(15) << 8) + tmp(16)
    call initialize_rand(seed)
    
    # For some extra randomness, can seed the rand generator using the ADC results  
    from internal temperature
        call hardware_adc_read(14, 3, 0)
    end
    
    event hardware_adc_result(input, value)
        if input = 14 then
            # Use ambient temperature check to augment seed
            seed = seed * (value & $ff)
            call initialize_rand(seed)
        end if
    end
    

    The 'randomness' of the generator can be viewed in this scatterplot - no obvious trends at a glance.

    enter image description here

    Once you have that, you can do similar to what Rich and John recommended by setting 'if' checks to generate your distribution. Please note that this code does not offer up a min/max value to generate a random between (due to not currently having a modulo implementation in BGScript).

    Pseudo-code might be:

    call rand()
    if rand_number <= PROBABILITY1 then
        # Show number 1
    end if
    if rand_number > PROBABILITY1 and rand_number <= PROBABILITY2 then
        # Show number 2
    end if
    if rand_number > PROBABILITY2 then
        # Show number 3
    end if