Skip to content

Instantly share code, notes, and snippets.

@atesgoral
Forked from 140bytes/LICENSE.txt
Last active January 26, 2017 19:17
Show Gist options
  • Save atesgoral/989140 to your computer and use it in GitHub Desktop.
Save atesgoral/989140 to your computer and use it in GitHub Desktop.
Significant figures with nearest integer rounding
// The idea is to:
// 1. shift the digits,
// 2. round to discard digits,
// 3. and shift back to restore magnitude.
// Numbers > 10 will be shifted to the right.
// Numbers < 10 will be shifted to the left.
(
n, // the number
s, // significant figures to round to
p // used as local variable to store power
) => {
with (Math) // will use a whole bunch of Math members
return p = s // compute power
- floor(
log(abs(n)) / LN10 // log10(abs(n))
)
- 1
, // comma operator allows executing all statements without {}
s = pow(10, p)// compute "shifter"
, // comma operator allows executing all statements without {}
(n = round(n * s) / s) // shave off figures using shifter
.toFixed(p<0?0:p) // include zeros after decimal for non-negative powers
}
(n,s,p)=>{with(Math)return p=s-floor(log(abs(n))/LN10)-1,s=pow(10,p),(round(n*s)/s).toFixed(p<0?0:p)}
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
Version 2, December 2004
Copyright (C) 2011 Ates Goral <http://magnetiq.com>
Everyone is permitted to copy and distribute verbatim or modified
copies of this license document, and changing it is allowed as long
as the name is changed.
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
0. You just DO WHAT THE FUCK YOU WANT TO.
{
"name": "significantFigures",
"description": "Rounds a number to the given number of significant figures.",
"keywords": [
"math",
"rounding",
"significant_figures"
]
}
var sigFigs = (n,s,p)=>{with(Math)return p=s-floor(log(abs(n))/LN10)-1,s=pow(10,p),(round(n*s)/s).toFixed(p<0?0:p)};
console.log(sigFigs(1234567, 3)); // 1230000
console.log(sigFigs(0.06805, 3)); // 0.0681
console.log(sigFigs(5, 3)); // 5.00
console.log(sigFigs(1.3, 2)); // 1.3
console.log(sigFigs(-1.3, 2)); // -1.3
console.log(sigFigs(-134, 2)); // -130
console.log(sigFigs(-135, 2)); // -130
console.log(sigFigs(-136, 2)); // -140
@wrayal
Copy link

wrayal commented May 30, 2011

Quite a neat method :)

Two suggestions:

  1. I'm guessing this won't work with negative numbers given that presumably JS won't handle logs of negative numbers? In that case, aren't we potentially safe to use the "0|" trick? (Although I guess this might mess up for numbers 0<n<1...)
  2. Might it not be faster doing "with(Math)"? I haven't checked yet...

@atesgoral
Copy link
Author

@wrayal:

  1. I think I'll have to release-note this limitation for now. I don't have a clean solution to add negative number support yet.
  2. Using with was a neat idea! I was using enough members of Math to justify it. Using with, along with a global leak fix, shaved off 9 bytes. Down to 77 bytes now.

@atesgoral
Copy link
Author

Down to 74 with floor -> ~~ hack

@wrayal
Copy link

wrayal commented Jun 3, 2011

I hate to be a killjoy, but the ~~ hack actually doesn't quite work here: compare Math.floor(-3.45) and ~~-3.45 ; they behave slightly differently for negative numbers, meaning that the method used in your count doesn't work for numbers n s.t. 0<n<1 =(

I've been trying to think of a neat way to fix it, but I'm not sure 3 bytes is enough breathing room!

Also, you can get negative numbers for only another 5 bytes now you're using with(Math) :)

function(n,s){with(Math)return s=pow(10,s-floor(log(abs(n))/LN10)-1),round(n*s)/s}

@atesgoral
Copy link
Author

I hate to be a killjoy

@wrayal, no joys have been harmed in the perfecting of this gist. Thank you very much for completing it by enabling negative number support! I think completeness is more important than byte crunching.

@atesgoral
Copy link
Author

Shaved some more bytes by using an arrow function. Now at 76.

@atesgoral
Copy link
Author

There's an outstanding issue. sigFigs(5, 3) should yield "5.00", not "5".

@atesgoral
Copy link
Author

atesgoral commented Jan 26, 2017

Fixed the mantissa issue. Now sigFigs(5, 3) correctly yields "5.00".

@atesgoral
Copy link
Author

Thanks to @paracycle for pointing out that this is specifically a "nearest integer rounding" flavour.

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