toFixed(2) not rounding?
Number.prototype.toFixed()
does not round a number. Use Math.round()
to do it. Also, result
already has the type Number
, so the parseFloat
is pretty much useless. Instead of:
result = parseFloat(result).toFixed(2)
use:
result = Math.round(result);
As a side note, don't use .map
as a substitute for .forEach
, meaning that this:
price.map((o,i)=>{
$(".subtotal").eq( i ).val(o*quantity[i]);
result += o*quantity[i];
});
should be this:
price.forEach((o, i) => {
$(".subtotal").eq( i ).val(o*quantity[i]);
result += o*quantity[i];
});
Furthermore, I would suggest to query the DOM once instead of several times, because traversing the DOM is a rather heavyweight operation.
Rounding in Javascript toFixed() method
As stated in the docs, toFixed()
does round when necessary. The rounding behavior is to round in the range -.5 < x <= +.5 of the digit.
The strange behavior you're observing is consistent with the note in the docs linked above:
Floating point numbers cannot represent all decimals precisely in binary which can lead to unexpected results such as 0.1 + 0.2 === 0.3 returning false .
In other words, this is a classic case of floating point precision loss - a problem you'll encounter in virtually any language. If you observe the full outputs of a
and b
you'll see that a == 0.075
and b == 0.07500000000000001
due to floating point precision - and thus given these values it is consistent with the defined rounding behavior to round a
to .07
and b
to .08
.
Rounding issue in Math.round() & .toFixed()
This method will give very correct round result.
function RoundNum(num, length) {
var number = Math.round(num * Math.pow(10, length)) / Math.pow(10, length);
return number;
}
Just call this method.
alert(RoundNum(192.168,2));
Reliable JS rounding numbers with toFixed(2) of a 3 decimal number
The toFixed()
method is unreliable in its rounding (see Álvaro González' answer as to why this is the case).
In both current Chrome and Firefox, calling toFixed()
yields the following inconsistent results:
35.655.toFixed(2) // Yields "36.66" (correct)
35.855.toFixed(2) // Yields "35.85" (wrong, should be "35.86")
MDN describes a reliable rounding implementation:
// Closure
(function() {
/**
* Decimal adjustment of a number.
*
* @param {String} type The type of adjustment.
* @param {Number} value The number.
* @param {Integer} exp The exponent (the 10 logarithm of the adjustment base).
* @returns {Number} The adjusted value.
*/
function decimalAdjust(type, value, exp) {
// If the exp is undefined or zero...
if (typeof exp === 'undefined' || +exp === 0) {
return Math[type](value);
}
value = +value;
exp = +exp;
// If the value is not a number or the exp is not an integer...
if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0)) {
return NaN;
}
// Shift
value = value.toString().split('e');
value = Math[type](+(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp)));
// Shift back
value = value.toString().split('e');
return +(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp));
}
// Decimal round
if (!Math.round10) {
Math.round10 = function(value, exp) {
return decimalAdjust('round', value, exp);
};
}
// Decimal floor
if (!Math.floor10) {
Math.floor10 = function(value, exp) {
return decimalAdjust('floor', value, exp);
};
}
// Decimal ceil
if (!Math.ceil10) {
Math.ceil10 = function(value, exp) {
return decimalAdjust('ceil', value, exp);
};
}
})();
// Round
Math.round10(55.55, -1); // 55.6
Math.round10(55.549, -1); // 55.5
Math.round10(55, 1); // 60
Math.round10(54.9, 1); // 50
Math.round10(-55.55, -1); // -55.5
Math.round10(-55.551, -1); // -55.6
Math.round10(-55, 1); // -50
Math.round10(-55.1, 1); // -60
Math.round10(1.005, -2); // 1.01 -- compare this with Math.round(1.005*100)/100 above
// Floor
Math.floor10(55.59, -1); // 55.5
Math.floor10(59, 1); // 50
Math.floor10(-55.51, -1); // -55.6
Math.floor10(-51, 1); // -60
// Ceil
Math.ceil10(55.51, -1); // 55.6
Math.ceil10(51, 1); // 60
Math.ceil10(-55.59, -1); // -55.5
Math.ceil10(-59, 1); // -50
Truncate number to two decimal places without rounding
Convert the number into a string, match the number up to the second decimal place:
function calc(theform) { var num = theform.original.value, rounded = theform.rounded var with2Decimals = num.toString().match(/^-?\d+(?:\.\d{0,2})?/)[0] rounded.value = with2Decimals}
<form onsubmit="return calc(this)">Original number: <input name="original" type="text" onkeyup="calc(form)" onchange="calc(form)" /><br />"Rounded" number: <input name="rounded" type="text" placeholder="readonly" readonly></form>
.toFixed() not rounding number correctly
Looks like your brackets are wrong, try something like this...
$('#h_prodcost').val(($(this).val()*100).toFixed());
You need to call toFixed()
before passing into .val()
.
Related Topics
How to Detect a Textbox's Content Has Changed
Disable Dragging an Image from an HTML Page
Syntax Highlighting Code with JavaScript
How to Generate the Opposite Color According to Current Color
How Does Facebook Rewrite the Source Url of a Page in the Browser Address Bar
Html5 Drag and Drop Anywhere on the Screen
Html5 Audio Tag on Safari Has a Delay
Multicolor Text Highlighting in a Textarea or Text Input
Uploading Multiple Files to Google Drive with Google App Script
Document.Getelementsbyclassname().Innerhtml Always Returns "Undefined"
How to Add Custom HTML Attributes in Jsx
Jquery Select Option Click Handler
Accessing Private Member Variables from Prototype-Defined Functions
JavaScript Filter Array Multiple Conditions