Rounding up to the nearest 0.05 in JavaScript - javascript

Question
Does anyone know of a way to round a float to the nearest 0.05 in JavaScript?
Example
BEFORE | AFTER
2.51 | 2.55
2.50 | 2.50
2.56 | 2.60
Current Code
var _ceil = Math.ceil;
Math.ceil = function(number, decimals){
if (arguments.length == 1)
return _ceil(number);
multiplier = Math.pow(10, decimals);
return _ceil(number * multiplier) / multiplier;
}
Then elsewhere...
return (Math.ceil((amount - 0.05), 1) + 0.05).toFixed(2);
Which is resulting in...
BEFORE | AFTER
2.51 | 2.55
2.50 | 2.55
2.56 | 2.65

Multiply by 20, then divide by 20:
(Math.ceil(number*20)/20).toFixed(2)

Rob's answer with my addition:
(Math.ceil(number*20 - 0.5)/20).toFixed(2)
Otherwise it always rounds up to the nearest 0.05.
** UPDATE **
Sorry has been pointed out this is not what the orig poster wanted.

I would go for the standard of actually dividing by the number you're factoring it to, and rounding that and multiplying it back again after. That seems to be a proper working method which you can use with any number and maintain the mental image of what you are trying to achieve.
var val = 26.14,
factor = 0.05;
val = Math.round(val / factor) * factor;
This will work for tens, hundreds or any number. If you are specifically rounding to the higher number then use Math.ceil instead of Math.round.
Another method specifically for rounding just to 1 or more decimal places (rather than half a place) is the following:
Number(Number(1.5454545).toFixed(1));
It creates a fixed number string and then turns it into a real Number.

I would write a function that does it for you by
move the decimal over two places (multiply by 100)
then mod (%) that inflatedNumber by 5 and get the remainder
subtract the remainder from 5 so that you know what the 'gap'(ceilGap) is between your number and the next closest .05
finally, divide your inflatedNumber by 100 so that it goes back to your original float, and voila, your num will be rounded up to the nearest .05.
function calcNearestPointZeroFive(num){
var inflatedNumber = num*100,
remainder = inflatedNumber % 5;
ceilGap = 5 - remainder
return (inflatedNumber + ceilGap)/100
}
If you want to leave numbers like 5.50 untouched you can always add this checker:
if (remainder===0){
return num
} else {
var ceilGap = 5 - remainder
return (inflatedNumber + ceilGap)/100
}

You need to put -1 to round half down and after that multiply by -1 like the example down bellow.
<script type="text/javascript">
function roundNumber(number, precision, isDown) {
var factor = Math.pow(10, precision);
var tempNumber = number * factor;
var roundedTempNumber = 0;
if (isDown) {
tempNumber = -tempNumber;
roundedTempNumber = Math.round(tempNumber) * -1;
} else {
roundedTempNumber = Math.round(tempNumber);
}
return roundedTempNumber / factor;
}
</script>
<div class="col-sm-12">
<p>Round number 1.25 down: <script>document.write(roundNumber(1.25, 1, true));</script>
</p>
<p>Round number 1.25 up: <script>document.write(roundNumber(1.25, 1, false));</script></p>
</div>

I ended up using this function in my project, successfully:
roundToNearestFiveCents( number: any ) {
return parseFloat((Math.round(number / 0.05) * 0.05).toFixed(2));
}
Might be of use to someone wanting to simply round to the nearest 5 cents on their monetary results, keeps the result a number, so if you perform addition on it further it won't result in string concatenation; also doesn't unnecessarily round up as a few of the other answers pointed out. Also limits it to two decimals, which is customary with finance.

My solution and test:
let round = function(number, precision = 2, rounding = 0.05) {
let multiply = 1 / rounding;
return parseFloat((Math.round(number * multiply) / multiply)).toFixed(precision);
};
https://jsfiddle.net/maciejSzewczyk/7r1tvhdk/40/

Even though the OP is not explicit about banker rounding, rounding up to the nearest $0.05 (5 cents) should be compatible with banker rounding. What suggested by Arth is more accurate than the accepted answer by Rob W.
(Math.ceil(number*20 - 0.5)/20).toFixed(2)
With banker rounding, you need a basic banker rounding function as suggested at Gaussian/banker's rounding in JavaScript, and I rewrite in TypeScript:
static bankerRound(num: number, decimalPlaces?: number) {
const d = decimalPlaces || 0;
const m = Math.pow(10, d);
const n = +(d ? num * m : num).toFixed(8);
const i = Math.floor(n), f = n - i;
const e = 1e-8;
const r = (f > 0.5 - e && f < 0.5 + e) ?
((i % 2 === 0) ? i : i + 1) : Math.round(n);
return d ? r / m : r;
}
static roundTo5cents(num: number) {
const r = bankerRound(Math.ceil(num * 20 - 0.5) / 20, 2);
return r;
}
The correctness of this algorithm could be verified through MBS Online, e.g. http://www9.health.gov.au/mbs/ready_reckoner.cfm?item_num=60

Related

How to round a number with multiple decimal places. Javascript

I am trying to create a function that can take a number and the number of decimal places and round the number to the exact decimal places that are going to be given.
I am using parseInt(prompt()) in order to gave the number and the number of decimal places.
For example,
round(3.141519, 2) -> 3.14
round(5986.32456, 4) -> 5986.3246
Can someone help me with this?
You can use toFixed
check the following
console.log(3.141519.toFixed(2))
console.log(5986.32456.toFixed(4))
Here is a short function that will allow you to specify the precision and returns a number:
function round(number, places) {
number = parseFloat(number, 10);
var e = parseInt(places || 2, 10);
var m = Math.pow(10, e);
return Math.floor(number * m) / m;
}
Or a slightly shorter ES6 function:
const round = (number, places=2) => {
const m = Math.pow(10, places);
return Math.floor(number * m) / m;
}

Round number to nearest .5 decimal

I'm looking for an output of
4.658227848101266 = 4.5
4.052117263843648 = 4.0
the closest I've gotten is
rating = (Math.round(rating * 4) / 4).toFixed(1)
but with this the number 4.658227848101266 = 4.8???
(Math.round(rating * 2) / 2).toFixed(1)
It's rather simple, you should multiply that number by 2, then round it and then divide it by 2:
var roundHalf = function(n) {
return (Math.round(n*2)/2).toFixed(1);
};
This works for me! (Using the closest possible format to yours)
rating = (Math.round(rating * 2) / 2).toFixed(1)
So this answer helped me. Here is a little bit o magic added to it to handle rounding to .5 or integer. Notice that the *2 and /2 is switched to /.5 and *.5 compared to every other answer.
/*
* #param {Number} n - pass in any number
* #param {Number} scale - either pass in .5 or 1
*/
var superCoolRound = function(n,scale) {
return (Math.round(n / scale) * scale).toFixed(1);
};
This is kinda late. But for someone who wants to round down to whole number or 0.5, you can try this:
function roundDown(number) {
var decimalPart = number % 1;
if (decimalPart < 0.5)
return number - decimalPart;
else
return number - decimalPart + 0.5;}
Late to this party, but I thought I would throw in a nice answer using a syntax I saw elsewhere, just in case someone comes across this in the future.
const roundDown = decimalNumber => {
return decimalNumber % 1 >= 0.5 ? +`${~~decimalNumber}.5` : ~~decimalNumber;
}
Explanation:
decimalNumber % 1 leaves you with only the decimal places
The + converts the string representation of your constructed number into a float, for consistency
~~decimalNumber drops the decimal places, leaving you with an integer
I assume you want to format the number for output and not truncate the precision. In that case, use a DecimalFormat. For example:
DecimalFormat df = new DecimalFormat("#.#");
df.format(rating);

How do you round to 1 decimal place in Javascript?

Can you round a number in javascript to 1 character after the decimal point (properly rounded)?
I tried the *10, round, /10 but it leaves two decimals at the end of the int.
Math.round(num * 10) / 10 works, here is an example...
var number = 12.3456789
var rounded = Math.round(number * 10) / 10
// rounded is 12.3
if you want it to have one decimal place, even when that would be a 0, then add...
var fixed = rounded.toFixed(1)
// fixed is always to 1 d.p.
// NOTE: .toFixed() returns a string!
// To convert back to number format
parseFloat(number.toFixed(2))
// 12.34
// but that will not retain any trailing zeros
// So, just make sure it is the last step before output,
// and use a number format during calculations!
EDIT: Add round with precision function...
Using this principle, for reference, here is a handy little round function that takes precision...
function round(value, precision) {
var multiplier = Math.pow(10, precision || 0);
return Math.round(value * multiplier) / multiplier;
}
... usage ...
round(12345.6789, 2) // 12345.68
round(12345.6789, 1) // 12345.7
... defaults to round to nearest whole number (precision 0) ...
round(12345.6789) // 12346
... and can be used to round to nearest 10 or 100 etc...
round(12345.6789, -1) // 12350
round(12345.6789, -2) // 12300
... and correct handling of negative numbers ...
round(-123.45, 1) // -123.4
round(123.45, 1) // 123.5
... and can be combined with toFixed to format consistently as string ...
round(456.7, 2).toFixed(2) // "456.70"
var number = 123.456;
console.log(number.toFixed(1)); // should round to 123.5
If you use Math.round(5.01) you will get 5 instead of 5.0.
If you use toFixed you run into rounding issues.
If you want the best of both worlds, combine the two:
(Math.round(5.01 * 10) / 10).toFixed(1)
You might want to create a function for this:
function roundedToFixed(input, digits){
var rounder = Math.pow(10, digits);
return (Math.round(input * rounder) / rounder).toFixed(digits);
}
lodash has a round method:
_.round(4.006);
// => 4
_.round(4.006, 2);
// => 4.01
_.round(4060, -2);
// => 4100
Docs.
Source.
You can simply do the following:
let n = 1.25
let result = Number(n).toFixed(1)
// output string: 1.3
I vote for toFixed(), but, for the record, here's another way that uses bit shifting to cast the number to an int. So, it always rounds towards zero (down for positive numbers, up for negatives).
var rounded = ((num * 10) << 0) * 0.1;
But hey, since there are no function calls, it's wicked fast. :)
And here's one that uses string matching:
var rounded = (num + '').replace(/(^.*?\d+)(\.\d)?.*/, '$1$2');
I don't recommend using the string variant, just sayin.
Try with this:
var original=28.453
// 1.- round "original" to two decimals
var result = Math.round (original * 100) / 100 //returns 28.45
// 2.- round "original" to 1 decimal
var result = Math.round (original * 10) / 10 //returns 28.5
// 3.- round 8.111111 to 3 decimals
var result = Math.round (8.111111 * 1000) / 1000 //returns 8.111
less complicated and easier to implement...
with this, you can create a function to do:
function RoundAndFix (n, d) {
var m = Math.pow (10, d);
return Math.round (n * m) / m;
}
function RoundAndFix (n, d) {
var m = Math.pow (10, d);
return Math.round (n * m) / m;
}
console.log (RoundAndFix(8.111111, 3));
EDIT: see this How to round using ROUND HALF UP. Rounding mode that most of us were taught in grade school
Why not just
let myNumber = 213.27321;
+myNumber.toFixed(1); // => 213.3
toFixed:
returns a string representing the given number using fixed-point notation.
Unary plus (+): The unary plus operator precedes its operand and evaluates to its operand but attempts to convert it into a number, if it isn't already.
In general, decimal rounding is done by scaling: round(num * p) / p
Naive implementation
Using the following function with halfway numbers, you will get either the upper rounded value as expected, or the lower rounded value sometimes depending on the input.
This inconsistency in rounding may introduce hard to detect bugs in the client code.
function naiveRound(num, decimalPlaces) {
var p = Math.pow(10, decimalPlaces);
return Math.round(num * p) / p;
}
console.log( naiveRound(1.245, 2) ); // 1.25 correct (rounded as expected)
console.log( naiveRound(1.255, 2) ); // 1.25 incorrect (should be 1.26)
Better implementations
By converting the number to a string in the exponential notation, positive numbers are rounded as expected.
But, be aware that negative numbers round differently than positive numbers.
In fact, it performs what is basically equivalent to "round half up" as the rule, you will see that round(-1.005, 2) evaluates to -1 even though round(1.005, 2) evaluates to 1.01. The lodash _.round method uses this technique.
/**
* Round half up ('round half towards positive infinity')
* Uses exponential notation to avoid floating-point issues.
* Negative numbers round differently than positive numbers.
*/
function round(num, decimalPlaces) {
num = Math.round(num + "e" + decimalPlaces);
return Number(num + "e" + -decimalPlaces);
}
// test rounding of half
console.log( round(0.5, 0) ); // 1
console.log( round(-0.5, 0) ); // 0
// testing edge cases
console.log( round(1.005, 2) ); // 1.01
console.log( round(2.175, 2) ); // 2.18
console.log( round(5.015, 2) ); // 5.02
console.log( round(-1.005, 2) ); // -1
console.log( round(-2.175, 2) ); // -2.17
console.log( round(-5.015, 2) ); // -5.01
If you want the usual behavior when rounding negative numbers, you would need to convert negative numbers to positive before calling Math.round(), and then convert them back to negative numbers before returning.
// Round half away from zero
function round(num, decimalPlaces) {
num = Math.round(Math.abs(num) + "e" + decimalPlaces) * Math.sign(num);
return Number(num + "e" + -decimalPlaces);
}
There is a different purely mathematical technique to perform round-to-nearest (using "round half away from zero"), in which epsilon correction is applied before calling the rounding function.
Simply, we add the smallest possible float value (= 1.0 ulp; unit in the last place) to the number before rounding. This moves to the next representable value after the number, away from zero.
/**
* Round half away from zero ('commercial' rounding)
* Uses correction to offset floating-point inaccuracies.
* Works symmetrically for positive and negative numbers.
*/
function round(num, decimalPlaces) {
var p = Math.pow(10, decimalPlaces);
var e = Number.EPSILON * num * p;
return Math.round((num * p) + e) / p;
}
// test rounding of half
console.log( round(0.5, 0) ); // 1
console.log( round(-0.5, 0) ); // -1
// testing edge cases
console.log( round(1.005, 2) ); // 1.01
console.log( round(2.175, 2) ); // 2.18
console.log( round(5.015, 2) ); // 5.02
console.log( round(-1.005, 2) ); // -1.01
console.log( round(-2.175, 2) ); // -2.18
console.log( round(-5.015, 2) ); // -5.02
This is needed to offset the implicit round-off error that may occur during encoding of decimal numbers, particularly those having "5" in the last decimal position, like 1.005, 2.675 and 16.235. Actually, 1.005 in decimal system is encoded to 1.0049999999999999 in 64-bit binary float; while, 1234567.005 in decimal system is encoded to 1234567.0049999998882413 in 64-bit binary float.
It is worth noting that the maximum binary round-off error is dependent upon (1) the magnitude of the number and (2) the relative machine epsilon (2^-52).
Using toPrecision method:
var a = 1.2345
a.toPrecision(2)
// result "1.2"
var num = 34.7654;
num = Math.round(num * 10) / 10;
console.log(num); // Logs: 34.8
To complete the Best Answer:
var round = function ( number, precision )
{
precision = precision || 0;
return parseFloat( parseFloat( number ).toFixed( precision ) );
}
The input parameter number may "not" always be a number, in this case .toFixed does not exist.
ES 6 Version of Accepted Answer:
function round(value, precision) {
const multiplier = 10 ** (precision || 0);
return Math.round(value * multiplier) / multiplier;
}
If your method does not work, plz post your code.
However,you could accomplish the rounding off task as:
var value = Math.round(234.567*100)/100
Will give you 234.56
Similarly
var value = Math.round(234.567*10)/10
Will give 234.5
In this way you can use a variable in the place of the constant as used above.
I made one that returns number type and also places decimals only if are needed (no 0 padding).
Examples:
roundWithMaxPrecision(11.234, 2); //11.23
roundWithMaxPrecision(11.234, 1); //11.2
roundWithMaxPrecision(11.234, 4); //11.23
roundWithMaxPrecision(11.234, -1); //10
roundWithMaxPrecision(4.2, 2); //4.2
roundWithMaxPrecision(4.88, 1); //4.9
The code:
function roundWithMaxPrecision (n, precision) {
const precisionWithPow10 = Math.pow(10, precision);
return Math.round(n * precisionWithPow10) / precisionWithPow10;
}
Little Angular filter if anyone wants it:
angular.module('filters').filter('decimalPlace', function() {
return function(num, precision) {
var multiplier = Math.pow(10, precision || 0);
return Math.round(num * multiplier) / multiplier;
};
});
use if via:
{{model.value| decimalPlace}}
{{model.value| decimalPlace:1}}
{{model.value| decimalPlace:2}}
:)
This seems to work reliably across anything I throw at it:
function round(val, multiplesOf) {
var s = 1 / multiplesOf;
var res = Math.ceil(val*s)/s;
res = res < val ? res + multiplesOf: res;
var afterZero = multiplesOf.toString().split(".")[1];
return parseFloat(res.toFixed(afterZero ? afterZero.length : 0));
}
It rounds up, so you may need to modify it according to use case. This should work:
console.log(round(10.01, 1)); //outputs 11
console.log(round(10.01, 0.1)); //outputs 10.1
If you care about proper rounding up then:
function roundNumericStrings(str , numOfDecPlacesRequired){
var roundFactor = Math.pow(10, numOfDecPlacesRequired);
return (Math.round(parseFloat(str)*roundFactor)/roundFactor).toString(); }
Else if you don't then you already have a reply from previous posts
str.slice(0, -1)
Math.round( num * 10) / 10 doesn't work.
For example, 1455581777.8-145558160.4 gives you 1310023617.3999999.
So only use num.toFixed(1)
I found a way to avoid the precision problems:
function badRound (num, precision) {
const x = 10 ** precision;
return Math.round(num * x) / x
}
// badRound(1.005, 2) --> 1
function round (num, precision) {
const x = 10 ** (precision + 1);
const y = 10 ** precision;
return Math.round(Math.round(num * x) / 10) / y
}
// round(1.005, 2) --> 1.01
Math.round( mul/count * 10 ) / 10
Math.round(Math.sqrt(sqD/y) * 10 ) / 10
Thanks
function rnd(v,n=2) {
return Math.round((v+Number.EPSILON)*Math.pow(10,n))/Math.pow(10,n)
}
this one catch the corner cases well
If your source code is typescript you could use a function like this:
public static ToFixedRounded(decimalNumber: number, fractionDigits: number): number {
var rounded = Math.pow(10, fractionDigits);
return (Math.round(decimalNumber * rounded) / rounded).toFixed(fractionDigits) as unknown as number;
}
const solds = 136780000000;
const number = (solds >= 1000000000 && solds < 1000000000000) ? { divisor: 1000000000, postfix: "B" }: (solds >= 1000000 && solds < 1000000000) ? { divisor: 1000000, postfix: "M" }: (solds >= 1000 && solds < 1000000) ? { divisor: 1000, postfix: "K" }: { divisor: 1, postfix: null };
const floor = Math.floor(solds / number.divisor).toLocaleString();
const firstDecimalIndex = solds.toLocaleString().charAt(floor.length+1);
const final =firstDecimalIndex.match("0")? floor + number.postfix: floor + "." + firstDecimalIndex + number.postfix;
console.log(final);
136780000000 --> 136.7B
1367800 --> 1.3M
1342 --> 1.3K

Round money to nearest 10 dollars in Javascript

How can I round a decimal number in Javascript to the nearest 10? My math is pretty rubbish today, it could be the 2 hour sleep :/
Some sample cases
$2823.66 = $2820
$142.11 = $140
$9.49 = $10
I understand I probably need a combination of Math.round/floor but I can't seem to get expected result.
Any help/pointers appreciated!
M
Try
Math.round(val / 10) * 10;
Use this function:
function roundTen(number)
{
return Math.round(number/10)*10;
}
alert(roundTen(2823.66));
To round a number to the nearest 10, first divide it by 10, then round it to the nearest 1, then multiply it by 10 again:
val = Math.round(val/10)*10;
This page has some details. They go the other way (e.g., rounding to the nearest 0.01) but the theory and practice are identical - multiply (or divide), round, then divide (or multiply).
10 * Math.round(val / 10)
function round(number, multiplier) {
multiplier = multiplier || 1;
return Math.round(number / multiplier) * multiplier;
}
var num1 = 2823.66;
var num2 = 142.11;
var num3 = 9.49;
console.log(
"%s\n%s\n%s", // just a formating thing
round(num1, 10), // 2820
round(num2, 10), // 140
round(num3, 10) // 10
);

Round a number to nearest .25 in JavaScript

I want to convert all numbers to the nearest .25
So...
5 becomes 5.00
2.25 becomes 2.25
4 becomes 4.00
3.5 becomes 3.50
Here’s an implementation of what rslite said:
var number = 5.12345;
number = (Math.round(number * 4) / 4).toFixed(2);
Multiply by 4, round to integer, divide by 4 and format with two decimals.
If speed is your concern, note that you can get about a 30% speed improvement by using:
var nearest = 4;
var rounded = number + nearest/2 - (number+nearest/2) % nearest;
From my website: http://phrogz.net/round-to-nearest-via-modulus-division
Performance tests here: http://jsperf.com/round-to-nearest
Here is a generic function to do rounding. In the examples above, 4 was used because that is in the inverse of .25. This function allows the user to ignore that detail. It doesn't currently support preset precision, but that can easily be added.
function roundToNearest(numToRound, numToRoundTo) {
numToRoundTo = 1 / (numToRoundTo);
return Math.round(numToRound * numToRoundTo) / numToRoundTo;
}
Here is #Gumbo's answer in a form of a function:
var roundNearQtr = function(number) {
return (Math.round(number * 4) / 4).toFixed(2);
};
You can now make calls:
roundNearQtr(5.12345); // 5.00
roundNearQtr(3.23); // 3.25
roundNearQtr(3.13); // 3.25
roundNearQtr(3.1247); // 3.00
function roundToInc(num, inc) {
const diff = num % inc;
return diff>inc/2?(num-diff+inc):num-diff;
}
> roundToInc(233223.2342343, 0.01)
233223.23
> roundToInc(505, 5)
505
> roundToInc(507, 5)
505
> roundToInc(508, 5)
510
Use below function, hope it helps
function roundByQuarter(value) {
var inv = 1.0 / 0.25;
return Math.round(value * inv) / inv;
}
Call the function as below, will result the nearest Quarter value, that is it will not return .32, .89, .56 but will return .25, .75, .50 decimals only.
roundByQuarter(2.74) = 2.75
roundByQuarter(2.34) = 2.25
roundByQuarter(2.94) = 3.00
roundByQuarter(2.24) = 2.25
A very good approximation for rounding:
function Rounding (number, precision){
var newNumber;
var sNumber = number.toString();
var increase = precision + sNumber.length - sNumber.indexOf('.') + 1;
if (number < 0)
newNumber = (number - 5 * Math.pow(10,-increase));
else
newNumber = (number + 5 * Math.pow(10,-increase));
var multiple = Math.pow(10,precision);
return Math.round(newNumber * multiple)/multiple;
}

Categories

Resources