Created
April 28, 2020 21:43
-
-
Save jwilson8767/ce39efd11ac69f253f5c1478cad0286c to your computer and use it in GitHub Desktop.
More javascript rounding options!
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
/* | |
I had trouble finding simple methods for rounding modes like half-even and | |
half-away-from-zero in Javascript, so here's what I came up with! Enjoy! | |
MIT licensed | |
*/ | |
/** | |
* Applies half-even rounding to the given number of significant figures. Supports n as a single value or series. | |
* @param {number} x Number to round | |
* @param {int} n Number of significant figures | |
* @return {number} | |
*/ | |
export function round_to_n_significant_figures(x, n) { | |
if ( n < 1){ | |
throw Error('Cannot round to less than 1 significant figures!') | |
} | |
return round_half_even(x, -Math.trunc(Math.floor(Math.log10(Math.abs(x)))) + (n - 1)) | |
} | |
/** | |
* Returns a number rounded using half-even rounding. Non-numeric values return NAN. Should match behavior of Python's round() function. | |
* @param {number} x Number to round | |
* @param {int} n Number of digits after the decimal point. May be negative to do things like `round_half_even(2500, -3) -> 2000`. | |
* @return {number} | |
*/ | |
export function round_half_even(x, n){ | |
x = Number(x); | |
if (Number.isNaN(x) || !Number.isFinite(x) || x === 0){ | |
return x | |
} | |
if (x < 0){ | |
return -round_half_even(-x, n) | |
} | |
x = x * Math.pow(10, n); | |
// figure out if the value is going to be a "half" value | |
const half = (x - Math.floor(x)) === 0.5; | |
// use Math.rounding (which uses half-up rounding), if not half not even, then subtract 1. | |
x = Math.round(x) | |
if (half && (x % 2 !== 0)){ | |
x = x - 1; | |
} | |
x = x / Math.pow(10, n) | |
return x | |
} | |
/** | |
* Returns a number rounded using half-away-from-0 rounding. | |
* @param {number} x Number to round | |
* @param {int} n Number of digits after the decimal point. May be negative to do things like `round_half_away_from_zero(2500, -3) -> 3000`. | |
* @return {number} | |
*/ | |
export function round_half_away_from_zero(x, n){ | |
x = Number(x); | |
if (Number.isNaN(x) || !Number.isFinite(x) || x === 0){ | |
return x | |
} | |
if (x < 0){ | |
// negative values just get inverted so we can use Math.round's half-up rounding | |
return -round_half_away_from_zero(-x, n) | |
} | |
return Math.round(x * Math.pow(10, n)) / Math.pow(10, n); | |
} | |
/** | |
* Returns a number rounded using half-toward-0 rounding. | |
* @param {number} x Number to round | |
* @param {int} n Number of digits after the decimal point. May be negative to do things like `round_half_toward_from_zero(2500, -3) -> 2000`. | |
* @return {number} | |
*/ | |
export function round_half_toward_from_zero(x, n){ | |
x = Number(x) | |
if (Number.isNaN(x) || x === 0){ | |
return x | |
} | |
if (x > 0){ | |
// negative values just get inverted so we can use Math.round's half-up rounding | |
return -round_half_away_from_zero(-x, n) | |
} | |
return Math.round(x * Math.pow(10, n-1)) / Math.pow(10, n-1); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
I do have a Python version of
round_to_n_significant_figures
as well, but you can probably just write the conversion yourself! Just remember that Python'sround()
does half-even rounding.