Reputation: 4487
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
Upvotes: 25
Views: 23536
Reputation: 2812
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
Upvotes: 1
Reputation: 193
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/
Upvotes: 1
Reputation: 13110
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.
Upvotes: 19
Reputation: 5601
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
.
Upvotes: 12
Reputation: 6309
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.
Upvotes: 1
Reputation: 59
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>
Upvotes: 1
Reputation: 41
I would write a function that does it for you by
%
) that inflatedNumber
by 5 and get the remainderremainder
from 5 so that you know what the 'gap'(ceilGap
) is between your number and the next closest .05finally, 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
}
Upvotes: 4
Reputation: 348972
Multiply by 20, then divide by 20:
(Math.ceil(number*20)/20).toFixed(2)
Upvotes: 50