Skip to content

Instantly share code, notes, and snippets.

@josher19
Created November 5, 2012 10:36
Show Gist options
  • Save josher19/4016552 to your computer and use it in GitHub Desktop.
Save josher19/4016552 to your computer and use it in GitHub Desktop.
Surreal Numbers (Conway)
// Surreal Number generation. Not exactly like Conway's version.
// 4 is [4]|[4] rather than [3]|[]
// so average of leftmost(left) and rightmost(right) is the value of the number
//
// Optimized for usage in Javascript and Node.
// TODO: Create Surreal class and github project.
function surreal_init(e) {
var left = [Math.floor(e)];
var right = [Math.ceil(e)];
return [left, right]
}
function surreal_next(left, e, right) {
var enext = (left[left.length-1] + right[0])/2
// Example: 2.6875
if (enext < e) left.push(enext)
else if (enext > e) right.unshift(enext)
else if (e == enext) return true
return false;
}
function surreal_toString(left, right) {
return [left,right].join("|")
// "2,2.5,2.625|2.75,3"
}
function surreal_approx(left,right) { return left[left.length-1] + "|" + right[0] }
// surreal_approx(left,right)
// "2.718281827867031|2.7182818297296762"
// Make surreal approaching e with total error of 2**-day.
function surreal_from(e, day) {
if (!day) day = 20;
var left=[Math.floor(e)], right=[Math.ceil(e)];
for(var done,d=0; d<day && !done; ++d) done = surreal_next(left, e, right);
return [left, right]
}
function surreal_error(left, e, right) { return [e - left[left.length-1], right[0] - e] }
function leftmost(left) { return left[left.length-1]; }
function rightmost(right) { return right[0]; }
// find out what day this surreal was created on
function generation(left,right,verbose) { if (null==right) {if (typeof left=="string") {left=left.split("|"); left[0]=left[0].split(","); left[1]=left[1].split(","); } right=left[1]; left=left[0]; } var gen = Math.abs(left[left.length-1] - right[0]); if (verbose) return [gen,-Math.log(gen)/Math.LN2,left,right]; return -Math.log(gen)/Math.LN2 }
// TODO: Make it more surreal for Integers
// surreal_from(5) = [[4],[]]
// DONE: surreal_from(0.5) = [[0],[1]]
// TODO: res.toString = function() { return this.join("|"); }
// res.valueOf = function() { return (this[0][this[0].length-1] + this[1][0])/2 }
@josher19
Copy link
Author

function Surreal(target, day) { 
  day = day || 54; 
  var left=Math.floor(target), right=left + 1, incr = 0.5; 
  this.day = day; 
  while(--day > 0) { 
    if (left + incr < target) left += incr; 
    if (right - incr> target) right -= incr; 
    incr *= 0.5; 
  }
  this.day -= day; 
  this.left = left; 
  this.right = right; 
  return this; 
}

Surreal.prototype.valueOf = function () { return (this.left + this.right) / 2 }
Surreal.prototype.toString = function() { return this.left + "|" + this.right }
Surreal.prototype.assertEquals = function (target,msg) { 
  var res = target === this.valueOf(); 
  console.assert(res, msg || ("Values do not match: " + target + " != " + this.valueOf())); 
  console.assert(this.left <= this.right, "left <= right failed"); 
  console.assert(this.toString().indexOf("|") > 0, "Surreal.prototype.toString failed"); 
  return res;  
}

new Surreal(Math.PI).assertEquals(Math.PI)
new Surreal(1/3).assertEquals(1/3)
new Surreal(3).assertEquals(3)
new Surreal(1e+21).assertEquals(1e+21)

@josher19
Copy link
Author

Surreal.prototype.gen = function (targ) { 
   var mygen = - Math.log(Math.abs(targ - this.left) + Math.abs(targ - this.right)) / Math.LN2; 
   return [mygen, mygen <= this.day, this.day]; 
}

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