Navigation Menu

Skip to content

Instantly share code, notes, and snippets.

@josher19
Created October 26, 2012 06:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save josher19/3957208 to your computer and use it in GitHub Desktop.
Save josher19/3957208 to your computer and use it in GitHub Desktop.
Random Numbers, including Surreal Decimals
// random number between -1 and 1 with 0 most common result, linearly decreasing
function triangle() { return Math.random() + Math.random() - 1.0 }
// random number between -1.5 and 1.5 with 0 most common, roughly following the bell curve
function bell() { return Math.random() + Math.random() + Math.random() - 1.5 }
// random number between -1.5e-300 and 1.5e+300 with 50% of the numbers between -0.75 and 0.75
function wild() { return (Math.random() + Math.random() + Math.random() - 1.5) / (Math.random()+1e-300) }
// show distribution counts after 10,000 runs.
// Example: testDistr(wild, 6);
function testDistr(fcn,k) {
var count={},sum=0,total=0; for(x=0; x<10000; ++x) {
var r;
++total;
sum += r = Math.round(k * fcn()) ;
count[r] = 1 + (count[r]||0);
};
var results = {count:count, sum:sum, total:total};
if (typeof console != "undefined" && typeof JSON != "undefined") console.log(JSON.stringify(results, null, " "));
return results;
}
// Find the maximum, minimum, and what percentage are less than range
function testBounds(count,range) {
var total = 0, sum = 0, max=-Infinity, min=Infinity;
for (x in count) {
if (!isNaN(x)) {
x=x-0; total += count[x];
if (x>max) max=x;
if (x<min) min=x;
if (Math.abs(x) <= range) sum += count[x]
}
}
return [max,min, 100 * sum / total]
}
/*
One way to quickly generate a random binary number is by looking at the decimal digits in math.random() and replace 0-4 with '1' and 5-9 with '1':
0.8430419054348022
becomes
1000001010001011
0.5513009827118367
becomes
1100001101001011
etc
*/
function toBinary(r) {
return r.split("").map(function(digit) { return digit >= "5" ? 1 : 0 })
}
function randomToBinary() {
return toBinary(Math.random().toString().substring(2))
}
// Note: always starts with "0." in binary form
function randomAsBinary() {
return Math.random().toString(2).substring(2)
}
/**
For a surreal-like decimal expansion, you need a random binary number.
*Even* bits tell you whether to stop or continue, *odd* bits tell you whether to go right or left on the tree:
> 0... => 0.0 [50%] Stop
> 100... => -0.5 [12.5%] Go, Left, Stop
> 110... => 0.5 [12.5%] Go, Right, Stop
> 11000... => 0.25 [<3.125%] Go, Right, Go, Left, Stop
> 11010... => 0.75 [<3.125%] Go, Right, Go, Right, Stop
> 1100100... => 0.125
> 1100110... => 0.375
> 1101100... => 0.625
> 1101110... => 0.875
> etc
*/
function toSurrealDecimal(list) {
list= list!=null ? list.slice().reverse() : randomToBinary();
var exp=0.5, sign, num=0;
list.pop();
while (list.length && list.pop()) {
sign=list.length && list.pop() ? -1 : 1;
num += sign*exp;
exp *= 0.5;
}
return num;
}
function randomSurreal() { return toSurrealDecimal(randomToBinary()) }
@josher19
Copy link
Author

// Add a wild integer and a random surreal decimal

function randomSurrealWild() { return Math.round(wild()*6) + randomSurreal() }

// Usage:

results = testDistr(randomSurrealWild, 1.0)

testBounds(results.count, 6)
[94307, -127684, 62.49]

testBounds(results.count, 6*1.5)
[94307, -127684, 73.79]

testBounds(results.count, 6*4.5)
[94307, -127684, 90.83]

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment