Created
October 26, 2012 06:21
-
-
Save josher19/3957208 to your computer and use it in GitHub Desktop.
Random Numbers, including Surreal Decimals
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// 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()) } | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
// 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]