Last active
January 23, 2021 23:21
-
-
Save pbatey/626d4f086ea64cab3c22f149900097e2 to your computer and use it in GitHub Desktop.
Show number as fraction in javascript
This file contains 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
/** | |
* Render a number as a fraction | |
* @param {number} v the decimal value to convert to a fraction | |
* @param {number[]} denom the list of denominators | |
* @returns {string} the fraction closest to the decimal value | |
*/ | |
const toFraction = (v, denom=[2,3,4,7,8,10,16,32,64,100]) => { | |
denom = denom.sort((a,b)=>a-b) | |
// whole and fractional parts | |
var w = Math.trunc(v) | |
const f = Math.abs(v - w) | |
// start with the max denom | |
var d = denom[denom.length-1] | |
var n = Math.round(d*f) | |
var delta = Math.abs(f - n/d) | |
// check if other denom are closer | |
for (var i=0; i < denom.length-1; i++) { | |
const d1 = denom[i] | |
const x = d1*f | |
const n1 = Math.round(x) | |
const delta1 = Math.abs(f - n1/d1) | |
if (n1 && delta1 <= delta) { | |
d = d1 | |
n = n1 | |
delta = delta1 | |
break | |
} | |
} | |
if (n == d) { | |
w++ | |
n = 0 | |
} | |
const result = [] | |
if (w !== 0) result.push(w) | |
if (n > 0) result.push(`${n}/${d}`) | |
return result.join(' ') | |
} | |
export default toFraction |
This file contains 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
import toFraction from './toFraction.mjs' | |
const data = [ | |
[0.004, '' ], // close to 0 | |
[0.005, '1/100' ], // close to 0 | |
[0.994, '99/100' ], // close to 1 | |
[0.995, '1' ], // close to 1 | |
[0.01, '1/100'], | |
[0.015625, '1/64'], // halfway between 1/100 and 1/64 - rounds up | |
[0.016, '1/64'], | |
[0.017, '1/64'], | |
[(.015625 + .02)/2, '2/100'], // halfway between 1/64 and 2/100 - rounds up | |
[0.018, '2/100'], | |
[0.02, '2/100'], | |
[0.03, '3/100'], | |
[(.03+1/32)/2, '1/32'], // halfway between 3/100 and 1/32 | |
[0.03125, '1/32'], | |
[0.035625, '1/32'], | |
[(1/32 + .04)/2, '4/100'], // halfway between 1/32 and 4/100 | |
[0.04, '4/100'], | |
[0.05, '5/100'], | |
[0.06, '6/100'], | |
[0.06125, '1/16'], // halfway between 6/100 and 1/16 - rounds up | |
[0.0625, '1/16'], | |
[0.06625, '1/16'], // halfway between 1/16 and 7/100 - rounds down | |
[0.07, '7/100'], | |
[0.08, '8/100'], | |
[0.09, '9/100'], | |
[0.1, '1/10'], | |
[(.1 + 1/7)/2, '12/100'], | |
[1/7, '1/7'], | |
[(1/7 + 1/8)/2, '13/100'], | |
[0.125, '1/8'], | |
[0.2, '2/10'], | |
[0.25, '1/4'], | |
[0.3125, '5/16'], | |
[0.33, '33/100'], | |
[0.3316, '33/100'], | |
[(.33 + (1/3))/2, '1/3'], // halfway between 33/100 and 1/3 - rounds up | |
[(1/3), '1/3'], | |
[((1/3) + .34)/2, '1/3'], // halfway between 1/3 and 34/100 - rounds down | |
[.3367, '34/100'], | |
[0.34, '34/100'], | |
[5/8, '5/8'], | |
[11/16, '11/16'], | |
[23/32, '23/32'], | |
[47/64, '47/64'], | |
[0.375, '3/8'], | |
[0.5, '1/2'], | |
[2/3, '2/3'], | |
[0.75, '3/4'], | |
[Math.PI, '3 1/7'], | |
[1.3333, '1 1/3'], | |
[-1.3333, '-1 1/3'], | |
[Math.PI, '3 16/113', [7,100,113,1000000]], // 355/113 is closer to PI than 3.141592, but not 3.1415926 | |
] | |
const negative = x => `\x1b[0;31m${x}\x1b[0;m` | |
const positive = x => `\x1b[0;32m${x}\x1b[0;m` | |
var failures = 0 | |
data.forEach(d => { | |
const [v,e, denom] = d | |
const f = toFraction(v, denom) | |
console.log('toFraction(',v,'): expect',f,'to be',e, f === e ? positive('pass') : negative('fail')) | |
failures += f === e ? 0 : 1 | |
}) | |
const vomit = '🤮' | |
const cheers = '🍻' | |
const passed = data.length - failures | |
console.log( // N passed, N failed emoji | |
passed, passed > 0 ? `${positive('passed')},` : 'passed,', | |
failures, failures > 0 ? negative('failed') : 'failed', | |
failures > 0 ? vomit : cheers) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment