Reputation: 11749
So I have a function that rounds to certain decimal scales
const roundNumber = (num, scale) => {
let n = num
switch(scale){
case 0.50:
n = (Math.ceil(num*2)/2).toFixed(2)
break;
case 0.25:
n = (Math.ceil(num*4)/4).toFixed(2)
break;
case 0.20:
n = (Math.ceil(num*5)/5).toFixed(2)
break;
case 0.10:
n = (Math.ceil(num*10)/10).toFixed(2)
break;
case 0.05:
n = (Math.ceil(num*20)/20).toFixed(2)
break;
}
return n
}
How would I adapt this to round to even smaller amounts such as...
0.000001, 0.000025, 0.000050, 0.0001,0.00025, 0.00050, 0.001 etc etc
So example.
0.48675387
I want to be able to output any of these amounts from this one number
0.48675000
0.48680000
0.48700000
0.49000000
0.50000000
Do I need to use a Big Number library for this? I can't think of how I would do this.
EDIT: Ive updated this with a table of values of inputs and outputs so you can see what I want to achieve. I basically want the number to snap to certain values, based on how close they are to them. Like normal rounding, but slightly different.
Scale Number Output
0.00025 0.45341000 0.45350
0.0025 0.45341000 0.4525 (closer to 0.4525 than 0.4550
0.005 0.45341000 0.455
0.01 0.45341000 0.45
See how the values differ if I simply just use toPrecision or toFixed
Number Output
0.45341000 0.45341
0.45341000 0.4534
0.45341000 0.453
0.45341000 0.45
Upvotes: 0
Views: 76
Reputation: 4198
I think the algorithm you're describing is:
In other words: "If I split this number into chunks of size scale
, then add one more chunk if the remainder is more than half of the scale
amount, and then put the chunks back together, what is the sum?"
function roundTo(scale, number) {
return Math.round(number / scale) * scale;
}
function roundTo(scale, number) {
return Math.round(number / scale) * scale;
}
const examples = [
{ scale: 0.00025, number: 0.45341000, expected: 0.45350 },
{ scale: 0.0025, number: 0.45341000, expected: 0.4525 },
{ scale: 0.005, number: 0.45341000, expected: 0.455 },
{ scale: 0.01, number: 0.45341000, expected: 0.45 },
]
examples.forEach(({ scale, number, expected }) => {
const actual = roundTo(scale, number);
const isExpectedResult = actual === expected ? '✅' : '❌';
console.log({ scale, number, expected, actual, isExpectedResult });
});
Upvotes: 0
Reputation: 23654
This isn't pretty but I'll put it down here and maybe come back to refine it. This should get you there though. Update: removed toPrecision early in the function since we're not using normal rounding.
function roundTo(num, scale) {
let arr, places, ref, lastx, remainder, thenum
arr = scale.toString().split(".")
places = arr[1].length; // get number decimal places
num = Number(num).toFixed(places); // get our starting number in the right format
ref=scale * Math.pow(10, places); // get our scale to the right format
lastx = Number(num.toString().substr(-(ref.toString().length))) // get the scale increment
remainder = lastx%ref; // modulus
if (remainder>=ref/2) thenum= Number((ref-remainder)*Math.pow(.1, places)) // if we need to add an amt
else thenum = Number(remainder*Math.pow(.1, places)) * -1 ; // if we need to substract an amt
thenum = thenum.toFixed(places) // fix our value
// console.log(places,num,ref,lastx,remainder,thenum);
num=(Number(num) + Number(thenum)).toFixed(places) // final calculation
return num;
}
console.log(roundTo(0.8946, 0.001));
console.log(roundTo(1.8946, 0.001));
Upvotes: 1
Reputation: 2244
Use Number.prototype.toPrecision()
let n = 0.48675387
n.toPrecision(5)
"0.48675"
n.toPrecision(4)
"0.4868"
n.toPrecision(3)
"0.487"
n.toPrecision(2)
"0.49"
n.toPrecision(1)
"0.5"
Upvotes: 1