Skip to content

Instantly share code, notes, and snippets.

@jeancroy
Forked from joni/float2rat.js
Last active December 21, 2017 20:44
Show Gist options
  • Save jeancroy/6103df5b5b9ebba8d3b6888113cb68ca to your computer and use it in GitHub Desktop.
Save jeancroy/6103df5b5b9ebba8d3b6888113cb68ca to your computer and use it in GitHub Desktop.
A JavaScript function to find short rational number representations of floating point numbers, with the help of some continued fractions.
// See http://jonisalonen.com/2012/converting-decimal-numbers-to-ratios/
// Also https://en.wikipedia.org/wiki/Diophantine_approximation
// or french https://fr.wikipedia.org/wiki/Fraction_continue_et_approximation_diophantienne
function float2rat(x) {
var tolerance = 1.0E-6;
var max_iter = 100; // Limit on the amount of work we want to do
var max_den = 1000; // When is a fraction not really more helpfull than decimal ?
//Integer
if( Math.abs(x - Math.round(x)) < tolerance )
return ""+Math.round(x);
// Store the sign and continue as positive number
var sgn = x>=0?1:-1;
x = Math.abs(x);
var b = x;
// Prepare continued fractions expansion
var h1=1; var h2=0;
var k1=0; var k2=1;
for(var i=0;i<max_iter;i++){
var a = Math.floor(b);
var tmp;
tmp = h1;
h1 = a*h1+h2;
h2 = tmp;
tmp = k1;
k1 = a*k1+k2;
k2 = tmp;
b = 1/(b-a);
// Success
if( Math.abs(k1*x-h1) <= k1*tolerance){
return sgn*h1+"/"+k1;
}
// Reached max denominator, nothing of interest, goto failure.
if(k1 >= max_den ){
break;
}
}
// Failure to find small fraction, present a decimal
return x.toFixed(6)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment