Formatting a number with exactly two decimals in JavaScript - javascript

I have this line of code which rounds my numbers to two decimal places. But I get numbers like this: 10.8, 2.4, etc. These are not my idea of two decimal places so how I can improve the following?
Math.round(price*Math.pow(10,2))/Math.pow(10,2);
I want numbers like 10.80, 2.40, etc. Use of jQuery is fine with me.

To format a number using fixed-point notation, you can simply use the toFixed method:
(10.8).toFixed(2); // "10.80"
var num = 2.4;
alert(num.toFixed(2)); // "2.40"
Note that toFixed() returns a string.
IMPORTANT: Note that toFixed does not round 90% of the time, it will return the rounded value, but for many cases, it doesn't work.
For instance:
2.005.toFixed(2) === "2.00"
UPDATE:
Nowadays, you can use the Intl.NumberFormat constructor. It's part of the ECMAScript Internationalization API Specification (ECMA402). It has pretty good browser support, including even IE11, and it is fully supported in Node.js.
const formatter = new Intl.NumberFormat('en-US', {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});
console.log(formatter.format(2.005)); // "2.01"
console.log(formatter.format(1.345)); // "1.35"
You can alternatively use the toLocaleString method, which internally will use the Intl API:
const format = (num, decimals) => num.toLocaleString('en-US', {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
});
console.log(format(2.005)); // "2.01"
console.log(format(1.345)); // "1.35"
This API also provides you a wide variety of options to format, like thousand separators, currency symbols, etc.

This is an old topic but still top-ranked Google results and the solutions offered share the same floating point decimals issue. Here is the (very generic) function I use, thanks to MDN:
function round(value, exp) {
if (typeof exp === 'undefined' || +exp === 0)
return Math.round(value);
value = +value;
exp = +exp;
if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0))
return NaN;
// Shift
value = value.toString().split('e');
value = Math.round(+(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));
}
As we can see, we don't get these issues:
round(1.275, 2); // Returns 1.28
round(1.27499, 2); // Returns 1.27
This genericity also provides some cool stuff:
round(1234.5678, -2); // Returns 1200
round(1.2345678e+2, 2); // Returns 123.46
round("123.45"); // Returns 123
Now, to answer the OP's question, one has to type:
round(10.8034, 2).toFixed(2); // Returns "10.80"
round(10.8, 2).toFixed(2); // Returns "10.80"
Or, for a more concise, less generic function:
function round2Fixed(value) {
value = +value;
if (isNaN(value))
return NaN;
// Shift
value = value.toString().split('e');
value = Math.round(+(value[0] + 'e' + (value[1] ? (+value[1] + 2) : 2)));
// Shift back
value = value.toString().split('e');
return (+(value[0] + 'e' + (value[1] ? (+value[1] - 2) : -2))).toFixed(2);
}
You can call it with:
round2Fixed(10.8034); // Returns "10.80"
round2Fixed(10.8); // Returns "10.80"
Various examples and tests (thanks to #t-j-crowder!):
function round(value, exp) {
if (typeof exp === 'undefined' || +exp === 0)
return Math.round(value);
value = +value;
exp = +exp;
if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0))
return NaN;
// Shift
value = value.toString().split('e');
value = Math.round(+(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));
}
function naive(value, exp) {
if (!exp) {
return Math.round(value);
}
var pow = Math.pow(10, exp);
return Math.round(value * pow) / pow;
}
function test(val, places) {
subtest(val, places);
val = typeof val === "string" ? "-" + val : -val;
subtest(val, places);
}
function subtest(val, places) {
var placesOrZero = places || 0;
var naiveResult = naive(val, places);
var roundResult = round(val, places);
if (placesOrZero >= 0) {
naiveResult = naiveResult.toFixed(placesOrZero);
roundResult = roundResult.toFixed(placesOrZero);
} else {
naiveResult = naiveResult.toString();
roundResult = roundResult.toString();
}
$("<tr>")
.append($("<td>").text(JSON.stringify(val)))
.append($("<td>").text(placesOrZero))
.append($("<td>").text(naiveResult))
.append($("<td>").text(roundResult))
.appendTo("#results");
}
test(0.565, 2);
test(0.575, 2);
test(0.585, 2);
test(1.275, 2);
test(1.27499, 2);
test(1234.5678, -2);
test(1.2345678e+2, 2);
test("123.45");
test(10.8034, 2);
test(10.8, 2);
test(1.005, 2);
test(1.0005, 2);
table {
border-collapse: collapse;
}
table, td, th {
border: 1px solid #ddd;
}
td, th {
padding: 4px;
}
th {
font-weight: normal;
font-family: sans-serif;
}
td {
font-family: monospace;
}
<table>
<thead>
<tr>
<th>Input</th>
<th>Places</th>
<th>Naive</th>
<th>Thorough</th>
</tr>
</thead>
<tbody id="results">
</tbody>
</table>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

I usually add this to my personal library, and after some suggestions and using the #TIMINeutron solution too, and making it adaptable for decimal length then, this one fits best:
function precise_round(num, decimals) {
var t = Math.pow(10, decimals);
return (Math.round((num * t) + (decimals>0?1:0)*(Math.sign(num) * (10 / Math.pow(100, decimals)))) / t).toFixed(decimals);
}
will work for the exceptions reported.

FAST AND EASY
parseFloat(number.toFixed(2))
Example
let number = 2.55435930
let roundedString = number.toFixed(2) // "2.55"
let twoDecimalsNumber = parseFloat(roundedString) // 2.55
let directly = parseFloat(number.toFixed(2)) // 2.55

One way to be 100% sure that you get a number with 2 decimals:
(Math.round(num*100)/100).toFixed(2)
If this causes rounding errors, you can use the following as James has explained in his comment:
(Math.round((num * 1000)/10)/100).toFixed(2)

I don't know why can't I add a comment to a previous answer (maybe I'm hopelessly blind, I don't know), but I came up with a solution using #Miguel's answer:
function precise_round(num,decimals) {
return Math.round(num*Math.pow(10, decimals)) / Math.pow(10, decimals);
}
And its two comments (from #bighostkim and #Imre):
Problem with precise_round(1.275,2) not returning 1.28
Problem with precise_round(6,2) not returning 6.00 (as he wanted).
My final solution is as follows:
function precise_round(num,decimals) {
var sign = num >= 0 ? 1 : -1;
return (Math.round((num*Math.pow(10,decimals)) + (sign*0.001)) / Math.pow(10,decimals)).toFixed(decimals);
}
As you can see I had to add a little bit of "correction" (it's not what it is, but since Math.round is lossy - you can check it on jsfiddle.net - this is the only way I knew how to "fix" it). It adds 0.001 to the already padded number, so it is adding a 1 three 0s to the right of the decimal value. So it should be safe to use.
After that I added .toFixed(decimal) to always output the number in the correct format (with the right amount of decimals).
So that's pretty much it. Use it well ;)
EDIT: added functionality to the "correction" of negative numbers.

toFixed(n) provides n length after the decimal point; toPrecision(x)
provides x total length.
Use this method below
// Example: toPrecision(4) when the number has 7 digits (3 before, 4 after)
// It will round to the tenths place
num = 500.2349;
result = num.toPrecision(4); // result will equal 500.2
AND if you want the number to be fixed use
result = num.toFixed(2);

I didn't find an accurate solution for this problem, so I created my own:
function inprecise_round(value, decPlaces) {
return Math.round(value*Math.pow(10,decPlaces))/Math.pow(10,decPlaces);
}
function precise_round(value, decPlaces){
var val = value * Math.pow(10, decPlaces);
var fraction = (Math.round((val-parseInt(val))*10)/10);
//this line is for consistency with .NET Decimal.Round behavior
// -342.055 => -342.06
if(fraction == -0.5) fraction = -0.6;
val = Math.round(parseInt(val) + fraction) / Math.pow(10, decPlaces);
return val;
}
Examples:
function inprecise_round(value, decPlaces) {
return Math.round(value * Math.pow(10, decPlaces)) / Math.pow(10, decPlaces);
}
function precise_round(value, decPlaces) {
var val = value * Math.pow(10, decPlaces);
var fraction = (Math.round((val - parseInt(val)) * 10) / 10);
//this line is for consistency with .NET Decimal.Round behavior
// -342.055 => -342.06
if (fraction == -0.5) fraction = -0.6;
val = Math.round(parseInt(val) + fraction) / Math.pow(10, decPlaces);
return val;
}
// This may produce different results depending on the browser environment
console.log("342.055.toFixed(2) :", 342.055.toFixed(2)); // 342.06 on Chrome & IE10
console.log("inprecise_round(342.055, 2):", inprecise_round(342.055, 2)); // 342.05
console.log("precise_round(342.055, 2) :", precise_round(342.055, 2)); // 342.06
console.log("precise_round(-342.055, 2) :", precise_round(-342.055, 2)); // -342.06
console.log("inprecise_round(0.565, 2) :", inprecise_round(0.565, 2)); // 0.56
console.log("precise_round(0.565, 2) :", precise_round(0.565, 2)); // 0.57

Here's a simple one
function roundFloat(num,dec){
var d = 1;
for (var i=0; i<dec; i++){
d += "0";
}
return Math.round(num * d) / d;
}
Use like alert(roundFloat(1.79209243929,4));
Jsfiddle

Round down
function round_down(value, decPlaces) {
return Math.floor(value * Math.pow(10, decPlaces)) / Math.pow(10, decPlaces);
}
Round up
function round_up(value, decPlaces) {
return Math.ceil(value * Math.pow(10, decPlaces)) / Math.pow(10, decPlaces);
}
Round nearest
function round_nearest(value, decPlaces) {
return Math.round(value * Math.pow(10, decPlaces)) / Math.pow(10, decPlaces);
}
Merged https://stackoverflow.com/a/7641824/1889449 and
https://www.kirupa.com/html5/rounding_numbers_in_javascript.htm Thanks
them.

Building on top of Christian C. Salvadó's answer, doing the following will output a Number type, and also seems to be dealing with rounding well:
const roundNumberToTwoDecimalPlaces = (num) => Number(new Intl.NumberFormat('en-US', {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
}).format(num));
roundNumberToTwoDecimalPlaces(1.344); // => 1.34
roundNumberToTwoDecimalPlaces(1.345); // => 1.35
The difference between the above and what has already been mentioned is that you don't need the .format() chaining when you're using it[, and that it outputs a Number type].

#heridev and I created a small function in jQuery.
You can try next:
HTML
<input type="text" name="one" class="two-digits"><br>
<input type="text" name="two" class="two-digits">​
jQuery
// apply the two-digits behaviour to elements with 'two-digits' as their class
$( function() {
$('.two-digits').keyup(function(){
if($(this).val().indexOf('.')!=-1){
if($(this).val().split(".")[1].length > 2){
if( isNaN( parseFloat( this.value ) ) ) return;
this.value = parseFloat(this.value).toFixed(2);
}
}
return this; //for chaining
});
});
​
DEMO ONLINE:
http://jsfiddle.net/c4Wqn/

The trouble with floating point values is that they are trying to represent an infinite amount of (continuous) values with a fixed amount of bits. So naturally, there must be some loss in play, and you're going to be bitten with some values.
When a computer stores 1.275 as a floating point value, it won't actually remember whether it was 1.275 or 1.27499999999999993, or even 1.27500000000000002. These values should give different results after rounding to two decimals, but they won't, since for computer they look exactly the same after storing as floating point values, and there's no way to restore the lost data. Any further calculations will only accumulate such imprecision.
So, if precision matters, you have to avoid floating point values from the start. The simplest options are to
use a devoted library
use strings for storing and passing around the values (accompanied by string operations)
use integers (e.g. you could be passing around the amount of hundredths of your actual value, e.g. amount in cents instead of amount in dollars)
For example, when using integers to store the number of hundredths, the function for finding the actual value is quite simple:
function descale(num, decimals) {
var hasMinus = num < 0;
var numString = Math.abs(num).toString();
var precedingZeroes = '';
for (var i = numString.length; i <= decimals; i++) {
precedingZeroes += '0';
}
numString = precedingZeroes + numString;
return (hasMinus ? '-' : '')
+ numString.substr(0, numString.length-decimals)
+ '.'
+ numString.substr(numString.length-decimals);
}
alert(descale(127, 2));
With strings, you'll need rounding, but it's still manageable:
function precise_round(num, decimals) {
var parts = num.split('.');
var hasMinus = parts.length > 0 && parts[0].length > 0 && parts[0].charAt(0) == '-';
var integralPart = parts.length == 0 ? '0' : (hasMinus ? parts[0].substr(1) : parts[0]);
var decimalPart = parts.length > 1 ? parts[1] : '';
if (decimalPart.length > decimals) {
var roundOffNumber = decimalPart.charAt(decimals);
decimalPart = decimalPart.substr(0, decimals);
if ('56789'.indexOf(roundOffNumber) > -1) {
var numbers = integralPart + decimalPart;
var i = numbers.length;
var trailingZeroes = '';
var justOneAndTrailingZeroes = true;
do {
i--;
var roundedNumber = '1234567890'.charAt(parseInt(numbers.charAt(i)));
if (roundedNumber === '0') {
trailingZeroes += '0';
} else {
numbers = numbers.substr(0, i) + roundedNumber + trailingZeroes;
justOneAndTrailingZeroes = false;
break;
}
} while (i > 0);
if (justOneAndTrailingZeroes) {
numbers = '1' + trailingZeroes;
}
integralPart = numbers.substr(0, numbers.length - decimals);
decimalPart = numbers.substr(numbers.length - decimals);
}
} else {
for (var i = decimalPart.length; i < decimals; i++) {
decimalPart += '0';
}
}
return (hasMinus ? '-' : '') + integralPart + (decimals > 0 ? '.' + decimalPart : '');
}
alert(precise_round('1.275', 2));
alert(precise_round('1.27499999999999993', 2));
Note that this function rounds to nearest, ties away from zero, while IEEE 754 recommends rounding to nearest, ties to even as the default behavior for floating point operations. Such modifications are left as an exercise for the reader :)

Round your decimal value, then use toFixed(x) for your expected digit(s).
function parseDecimalRoundAndFixed(num,dec){
var d = Math.pow(10,dec);
return (Math.round(num * d) / d).toFixed(dec);
}
Call
parseDecimalRoundAndFixed(10.800243929,4) => 10.80
parseDecimalRoundAndFixed(10.807243929,2) => 10.81

Number(Math.round(1.005+'e2')+'e-2'); // 1.01
This worked for me: Rounding Decimals in JavaScript

With these examples you will still get an error when trying to round the number 1.005 the solution is to either use a library like Math.js or this function:
function round(value: number, decimals: number) {
return Number(Math.round(value + 'e' + decimals) + 'e-' + decimals);
}

Here is my 1-line solution: Number((yourNumericValueHere).toFixed(2));
Here's what happens:
1) First, you apply .toFixed(2) onto the number that you want to round off the decimal places of. Note that this will convert the value to a string from number. So if you are using Typescript, it will throw an error like this:
"Type 'string' is not assignable to type 'number'"
2) To get back the numeric value or to convert the string to numeric value, simply apply the Number() function on that so-called 'string' value.
For clarification, look at the example below:
EXAMPLE:
I have an amount that has upto 5 digits in the decimal places and I would like to shorten it to upto 2 decimal places. I do it like so:
var price = 0.26453;
var priceRounded = Number((price).toFixed(2));
console.log('Original Price: ' + price);
console.log('Price Rounded: ' + priceRounded);

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).

Put the following in some global scope:
Number.prototype.getDecimals = function ( decDigCount ) {
return this.toFixed(decDigCount);
}
and then try:
var a = 56.23232323;
a.getDecimals(2); // will return 56.23
Update
Note that toFixed() can only work for the number of decimals between 0-20 i.e. a.getDecimals(25) may generate a javascript error, so to accomodate that you may add some additional check i.e.
Number.prototype.getDecimals = function ( decDigCount ) {
return ( decDigCount > 20 ) ? this : this.toFixed(decDigCount);
}

Number(((Math.random() * 100) + 1).toFixed(2))
this will return a random number from 1 to 100 rounded to 2 decimal places.

Using this response by reference: https://stackoverflow.com/a/21029698/454827
I build a function to get dynamic numbers of decimals:
function toDec(num, dec)
{
if(typeof dec=='undefined' || dec<0)
dec = 2;
var tmp = dec + 1;
for(var i=1; i<=tmp; i++)
num = num * 10;
num = num / 10;
num = Math.round(num);
for(var i=1; i<=dec; i++)
num = num / 10;
num = num.toFixed(dec);
return num;
}
here working example: https://jsfiddle.net/wpxLduLc/

parse = function (data) {
data = Math.round(data*Math.pow(10,2))/Math.pow(10,2);
if (data != null) {
var lastone = data.toString().split('').pop();
if (lastone != '.') {
data = parseFloat(data);
}
}
return data;
};
$('#result').html(parse(200)); // output 200
$('#result1').html(parse(200.1)); // output 200.1
$('#result2').html(parse(200.10)); // output 200.1
$('#result3').html(parse(200.109)); // output 200.11
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<div id="result"></div>
<div id="result1"></div>
<div id="result2"></div>
<div id="result3"></div>

I got some ideas from this post a few months back, but none of the answers here, nor answers from other posts/blogs could handle all the scenarios (e.g. negative numbers and some "lucky numbers" our tester found). In the end, our tester did not find any problem with this method below. Pasting a snippet of my code:
fixPrecision: function (value) {
var me = this,
nan = isNaN(value),
precision = me.decimalPrecision;
if (nan || !value) {
return nan ? '' : value;
} else if (!me.allowDecimals || precision <= 0) {
precision = 0;
}
//[1]
//return parseFloat(Ext.Number.toFixed(parseFloat(value), precision));
precision = precision || 0;
var negMultiplier = value < 0 ? -1 : 1;
//[2]
var numWithExp = parseFloat(value + "e" + precision);
var roundedNum = parseFloat(Math.round(Math.abs(numWithExp)) + 'e-' + precision) * negMultiplier;
return parseFloat(roundedNum.toFixed(precision));
},
I also have code comments (sorry i forgot all the details already)...I'm posting my answer here for future reference:
9.995 * 100 = 999.4999999999999
Whereas 9.995e2 = 999.5
This discrepancy causes Math.round(9.995 * 100) = 999 instead of 1000.
Use e notation instead of multiplying /dividing by Math.Pow(10,precision).

I'm fix the problem the modifier.
Support 2 decimal only.
$(function(){
//input number only.
convertNumberFloatZero(22); // output : 22.00
convertNumberFloatZero(22.5); // output : 22.50
convertNumberFloatZero(22.55); // output : 22.55
convertNumberFloatZero(22.556); // output : 22.56
convertNumberFloatZero(22.555); // output : 22.55
convertNumberFloatZero(22.5541); // output : 22.54
convertNumberFloatZero(22222.5541); // output : 22,222.54
function convertNumberFloatZero(number){
if(!$.isNumeric(number)){
return 'NaN';
}
var numberFloat = number.toFixed(3);
var splitNumber = numberFloat.split(".");
var cNumberFloat = number.toFixed(2);
var cNsplitNumber = cNumberFloat.split(".");
var lastChar = splitNumber[1].substr(splitNumber[1].length - 1);
if(lastChar > 0 && lastChar < 5){
cNsplitNumber[1]--;
}
return Number(splitNumber[0]).toLocaleString('en').concat('.').concat(cNsplitNumber[1]);
};
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>

(Math.round((10.2)*100)/100).toFixed(2)
That should yield: 10.20
(Math.round((.05)*100)/100).toFixed(2)
That should yield: 0.05
(Math.round((4.04)*100)/100).toFixed(2)
That should yield: 4.04
etc.

/*Due to all told stuff. You may do 2 things for different purposes:
When showing/printing stuff use this in your alert/innerHtml= contents:
YourRebelNumber.toFixed(2)*/
var aNumber=9242.16;
var YourRebelNumber=aNumber-9000;
alert(YourRebelNumber);
alert(YourRebelNumber.toFixed(2));
/*and when comparing use:
Number(YourRebelNumber.toFixed(2))*/
if(YourRebelNumber==242.16)alert("Not Rounded");
if(Number(YourRebelNumber.toFixed(2))==242.16)alert("Rounded");
/*Number will behave as you want in that moment. After that, it'll return to its defiance.
*/

This is very simple and works just as well as any of the others:
function parseNumber(val, decimalPlaces) {
if (decimalPlaces == null) decimalPlaces = 0
var ret = Number(val).toFixed(decimalPlaces)
return Number(ret)
}
Since toFixed() can only be called on numbers, and unfortunately returns a string, this does all the parsing for you in both directions. You can pass a string or a number, and you get a number back every time! Calling parseNumber(1.49) will give you 1, and parseNumber(1.49,2) will give you 1.50. Just like the best of 'em!

You could also use the .toPrecision() method and some custom code, and always round up to the nth decimal digit regardless the length of int part.
function glbfrmt (number, decimals, seperator) {
return typeof number !== 'number' ? number : number.toPrecision( number.toString().split(seperator)[0].length + decimals);
}
You could also make it a plugin for a better use.

Here's a TypeScript implementation of https://stackoverflow.com/a/21323330/916734. It also dries things up with functions, and allows for a optional digit offset.
export function round(rawValue: number | string, precision = 0, fractionDigitOffset = 0): number | string {
const value = Number(rawValue);
if (isNaN(value)) return rawValue;
precision = Number(precision);
if (precision % 1 !== 0) return NaN;
let [ stringValue, exponent ] = scientificNotationToParts(value);
let shiftExponent = exponentForPrecision(exponent, precision, Shift.Right);
const enlargedValue = toScientificNotation(stringValue, shiftExponent);
const roundedValue = Math.round(enlargedValue);
[ stringValue, exponent ] = scientificNotationToParts(roundedValue);
const precisionWithOffset = precision + fractionDigitOffset;
shiftExponent = exponentForPrecision(exponent, precisionWithOffset, Shift.Left);
return toScientificNotation(stringValue, shiftExponent);
}
enum Shift {
Left = -1,
Right = 1,
}
function scientificNotationToParts(value: number): Array<string> {
const [ stringValue, exponent ] = value.toString().split('e');
return [ stringValue, exponent ];
}
function exponentForPrecision(exponent: string, precision: number, shift: Shift): number {
precision = shift * precision;
return exponent ? (Number(exponent) + precision) : precision;
}
function toScientificNotation(value: string, exponent: number): number {
return Number(`${value}e${exponent}`);
}

fun Any.twoDecimalPlaces(numInDouble: Double): String {
return "%.2f".format(numInDouble)
}

Related

How to truncate decimals in JavaScript without Math library?

I need numbers to have only 2 decimals (as in money), and I was using this:
Number(parseFloat(Math.trunc(amount_to_truncate * 100) / 100));
But I can no longer support the Math library.
How can I achieve this without the Math library AND withou rounding the decimals?
You can use toFixed
Number(amount_to_truncate.toFixed(2))
If you are sure that your input always will be lower or equal than 21474836.47 ((2^31 - 1) / 100) (32bit) then:
if you need as string (to make sure result will have 2 decimals)
((amount_to_truncate * 100|0)/100).toFixed(2)
Otherwise
((amount_to_truncate * 100|0)/100)
Else: See Nina Schols's answer
console.log((((15.555 * 100)|0)/100)) // will not round: 15.55
console.log((((15 * 100)|0)/100).toFixed(2)) // will not round: 15.55
Make it simple
const trunc = (n, decimalPlaces) => {
const decimals = decimalPlaces ? decimalPlaces : 2;
const asString = n.toString();
const pos = asString.indexOf('.') != -1 ? asString.indexOf('.') + decimals + 1 : asString.length;
return parseFloat(n.toString().substring(0, pos));
};
console.log(trunc(3.14159265359));
console.log(trunc(11.1111111));
console.log(trunc(3));
console.log(trunc(11));
console.log(trunc(3.1));
console.log(trunc(11.1));
console.log(trunc(3.14));
console.log(trunc(11.11));
console.log(trunc(3.141));
console.log(trunc(11.111));
The only thing I see wrong with toFixed is that it rounds the precision which OP specifically states they don't want to do. Truncate is more equivalent to floor for positive numbers and ceil for negative than round or toFixed. On the MDN page for the Math.trunc there is a polyfill replacement function that would do what OP is expecting.
Math.trunc = Math.trunc || function(x) {
return x - x % 1;
}
If you just used that, then the code wouldn't have to change.
You could use parseInt for a non rounded number.
console.log(parseInt(15.555 * 100, 10) / 100); // 15.55 no rounding
console.log((15.555 * 100 | 0) / 100); // 15.55 no rounding, 32 bit only
console.log((15.555).toFixed(2)); // 15.56 rounding
Try using toFixed:
number.toFixed(2)
Truncate does also a rounding, so your statement: "I need numbers to have only 2 decimals ... without rounding the decimals" seems to me a little bit convoluted and would lead to a long discussion.
Beside this, when dealing with money, the problem isn't Math but how you are using it. I suggest you read the Floating-point cheat sheet for JavaScript - otherwise you will fail even with a simple calculation like 1.40 - 1.00.
The solution to your question is to use a well-tested library for arbitrary-precision decimals like bignumber.js or decimals.js (just as an example).
EDIT:
If you absolutely need a snippet, this is how i did it some time ago:
function round2(d) { return Number(((d+'e'+2)|0)+'e-'+2); }
You could parseInt to truncate, then divide by 100 and parseFloat.
var num = 123.4567;
num=parseInt(num*100);
num=parseFloat(num/100);
alert(num);
See fiddle
Edit: in order to deal with javascript math craziness, you can use .toFixed and an additional digit of multiplication/division:
var num = 123.4567;
num = (num*1000).toFixed();
num = parseInt(num/10);
num = parseFloat(num/100);
alert(num);
Updated fiddle
This was a lot easier than I thought:
const trunc = (number, precision) => {
let index = number.toString().indexOf(".");
let subStr;
// in case of no decimal
if (index === -1) {
subStr = number.toString();
}
// in case of 0 precision
else if (precision === 0) {
subStr = number.toString().substring(0, index);
}
// all else
else {
subStr = number.toString().substring(0, index + 1 + precision);
}
return parseFloat(subStr);
};
let x = trunc(99.12, 1);
console.log("x", x);
You can try this
function trunc(value){
return (!!value && typeof value == "number")? value - value%1 : 0;
}
console.log(trunc(1.4));
console.log(trunc(111.9));
console.log(trunc(0.4));
console.log(trunc("1.4"));

toFixed method without rounding to five digit

I have a number var x = 2.305185185185195;
x = x.toFixed(5);
x = 2.30519 but I require this without rounding i.e. 2.30518
I read some thread with two decimal places but could not find for five decimal places.
Any help would be appreciated.
You can use an apropriate factor and floor it and return the result of the division.
Basically this solution moves the point to the left with a factor of 10^d and gets an integer of that and divided the value with the former factor to get the right digits.
function getFlooredFixed(v, d) {
return (Math.floor(v * Math.pow(10, d)) / Math.pow(10, d)).toFixed(d);
}
var x = 2.305185185185195;
document.write(getFlooredFixed(x, 5));
If you need only a "part" of a number with a floating point without rounding, you can just "cut" it:
function cutNumber(number, digitsAfterDot) {
const str = `${number}`;
return str.slice(0, str.indexOf('.') + digitsAfterDot + 1);
}
const x = 2.305185185185195;
console.log(cutNumber(x, 5)); // 2.30518
This method is fast (https://jsfiddle.net/93m8akzo/1/) and its execution time doesn't depend on number or digitsAfterDot values.
You can also "play around" with both functions in a given fiddle for a better understanding of what they do.
You can read more about slice() method here - MDN documentation
NOTE This function is only an example, don't use it in production applications.
You should definitely add input values validation and errors handling!
The Math.trunc() function returns the integer part of a number by
removing any fractional digits
So you can multiply the number by 10^n where n is the desired number of precision, truncate the decimal part using Math.trunc(), divide by the same number (10^n) and apply toFixed() to format it (in order to get the form of 2.30 instead of 2.3 for example)
var x = 2.305185185185195;
console.log((Math.trunc(x*100000)/100000).toFixed(5));
I have sorted it out by adding a small amount if the decimal is 5, then rounding as usual:
function(value, decimals) {
var decimals = decimals || 2;
if( isNaN(value) ){ return 0; }
var decimalPart = value.toString().trim().split('.').pop(),
extra = decimalPart.substr(decimals, decimalPart.length - decimals);
if( extra == '5' &&
decimalPart.length > decimals
){
value = parseFloat(value) + (1 / ( Math.pow(10, decimals + 5) ) );
}
return Number( parseFloat( value ).toFixed( decimals ) );
}

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

Truncate (not round off) decimal numbers in javascript

I am trying to truncate decimal numbers to decimal places. Something like this:
5.467 -> 5.46
985.943 -> 985.94
toFixed(2) does just about the right thing but it rounds off the value. I don't need the value rounded off. Hope this is possible in javascript.
Dogbert's answer is good, but if your code might have to deal with negative numbers, Math.floor by itself may give unexpected results.
E.g. Math.floor(4.3) = 4, but Math.floor(-4.3) = -5
Use a helper function like this one instead to get consistent results:
truncateDecimals = function (number) {
return Math[number < 0 ? 'ceil' : 'floor'](number);
};
// Applied to Dogbert's answer:
var a = 5.467;
var truncated = truncateDecimals(a * 100) / 100; // = 5.46
Here's a more convenient version of this function:
truncateDecimals = function (number, digits) {
var multiplier = Math.pow(10, digits),
adjustedNum = number * multiplier,
truncatedNum = Math[adjustedNum < 0 ? 'ceil' : 'floor'](adjustedNum);
return truncatedNum / multiplier;
};
// Usage:
var a = 5.467;
var truncated = truncateDecimals(a, 2); // = 5.46
// Negative digits:
var b = 4235.24;
var truncated = truncateDecimals(b, -2); // = 4200
If that isn't desired behaviour, insert a call to Math.abs on the first line:
var multiplier = Math.pow(10, Math.abs(digits)),
EDIT: shendz correctly points out that using this solution with a = 17.56 will incorrectly produce 17.55. For more about why this happens, read What Every Computer Scientist Should Know About Floating-Point Arithmetic. Unfortunately, writing a solution that eliminates all sources of floating-point error is pretty tricky with javascript. In another language you'd use integers or maybe a Decimal type, but with javascript...
This solution should be 100% accurate, but it will also be slower:
function truncateDecimals (num, digits) {
var numS = num.toString(),
decPos = numS.indexOf('.'),
substrLength = decPos == -1 ? numS.length : 1 + decPos + digits,
trimmedResult = numS.substr(0, substrLength),
finalResult = isNaN(trimmedResult) ? 0 : trimmedResult;
return parseFloat(finalResult);
}
For those who need speed but also want to avoid floating-point errors, try something like BigDecimal.js. You can find other javascript BigDecimal libraries in this SO question: "Is there a good Javascript BigDecimal library?" and here's a good blog post about math libraries for Javascript
upd:
So, after all it turned out, rounding bugs will always haunt you, no matter how hard you try to compensate them. Hence the problem should be attacked by representing numbers exactly in decimal notation.
Number.prototype.toFixedDown = function(digits) {
var re = new RegExp("(\\d+\\.\\d{" + digits + "})(\\d)"),
m = this.toString().match(re);
return m ? parseFloat(m[1]) : this.valueOf();
};
[ 5.467.toFixedDown(2),
985.943.toFixedDown(2),
17.56.toFixedDown(2),
(0).toFixedDown(1),
1.11.toFixedDown(1) + 22];
// [5.46, 985.94, 17.56, 0, 23.1]
Old error-prone solution based on compilation of others':
Number.prototype.toFixedDown = function(digits) {
var n = this - Math.pow(10, -digits)/2;
n += n / Math.pow(2, 53); // added 1360765523: 17.56.toFixedDown(2) === "17.56"
return n.toFixed(digits);
}
var a = 5.467;
var truncated = Math.floor(a * 100) / 100; // = 5.46
You can fix the rounding by subtracting 0.5 for toFixed, e.g.
(f - 0.005).toFixed(2)
Nice one-line solution:
function truncate (num, places) {
return Math.trunc(num * Math.pow(10, places)) / Math.pow(10, places);
}
Then call it with:
truncate(3.5636232, 2); // returns 3.56
truncate(5.4332312, 3); // returns 5.433
truncate(25.463214, 4); // returns 25.4632
Consider taking advantage of the double tilde: ~~.
Take in the number. Multiply by significant digits after the decimal so that you can truncate to zero places with ~~. Divide that multiplier back out. Profit.
function truncator(numToTruncate, intDecimalPlaces) {
var numPower = Math.pow(10, intDecimalPlaces); // "numPowerConverter" might be better
return ~~(numToTruncate * numPower)/numPower;
}
I'm trying to resist wrapping the ~~ call in parens; order of operations should make that work correctly, I believe.
alert(truncator(5.1231231, 1)); // is 5.1
alert(truncator(-5.73, 1)); // is -5.7
alert(truncator(-5.73, 0)); // is -5
JSFiddle link.
EDIT: Looking back over, I've unintentionally also handled cases to round off left of the decimal as well.
alert(truncator(4343.123, -2)); // gives 4300.
The logic's a little wacky looking for that usage, and may benefit from a quick refactor. But it still works. Better lucky than good.
I thought I'd throw in an answer using | since it is simple and works well.
truncate = function(number, places) {
var shift = Math.pow(10, places);
return ((number * shift) | 0) / shift;
};
Truncate using bitwise operators:
~~0.5 === 0
~~(-0.5) === 0
~~14.32794823 === 14
~~(-439.93) === -439
#Dogbert's answer can be improved with Math.trunc, which truncates instead of rounding.
There is a difference between rounding and truncating. Truncating is
clearly the behaviour this question is seeking. If I call
truncate(-3.14) and receive -4 back, I would definitely call that
undesirable. – #NickKnowlson
var a = 5.467;
var truncated = Math.trunc(a * 100) / 100; // = 5.46
var a = -5.467;
var truncated = Math.trunc(a * 100) / 100; // = -5.46
I wrote an answer using a shorter method. Here is what I came up with
function truncate(value, precision) {
var step = Math.pow(10, precision || 0);
var temp = Math.trunc(step * value);
return temp / step;
}
The method can be used like so
truncate(132456.25456789, 5)); // Output: 132456.25456
truncate(132456.25456789, 3)); // Output: 132456.254
truncate(132456.25456789, 1)); // Output: 132456.2
truncate(132456.25456789)); // Output: 132456
Or, if you want a shorter syntax, here you go
function truncate(v, p) {
var s = Math.pow(10, p || 0);
return Math.trunc(s * v) / s;
}
I think this function could be a simple solution:
function trunc(decimal,n=2){
let x = decimal + ''; // string
return x.lastIndexOf('.')>=0?parseFloat(x.substr(0,x.lastIndexOf('.')+(n+1))):decimal; // You can use indexOf() instead of lastIndexOf()
}
console.log(trunc(-241.31234,2));
console.log(trunc(241.312,5));
console.log(trunc(-241.233));
console.log(trunc(241.2,0));
console.log(trunc(241));
Number.prototype.trim = function(decimals) {
var s = this.toString();
var d = s.split(".");
d[1] = d[1].substring(0, decimals);
return parseFloat(d.join("."));
}
console.log((5.676).trim(2)); //logs 5.67
I'm a bit confused as to why there are so many different answers to such a fundamentally simple question; there are only two approaches which I saw which seemed to be worth looking at. I did a quick benchmark to see the speed difference using https://jsbench.me/.
This is the solution which is currently (9/26/2020) flagged as the answer:
function truncate(n, digits) {
var re = new RegExp("(\\d+\\.\\d{" + digits + "})(\\d)"),
m = n.toString().match(re);
return m ? parseFloat(m[1]) : n.valueOf();
};
[ truncate(5.467,2),
truncate(985.943,2),
truncate(17.56,2),
truncate(0, 1),
truncate(1.11, 1) + 22];
However, this is doing string and regex stuff, which is usually not very efficient, and there is a Math.trunc function which does exactly what the OP wants just with no decimals. Therefore, you can easily use that plus a little extra arithmetic to get the same thing.
Here is another solution I found on this thread, which is the one I would use:
function truncate(n, digits) {
var step = Math.pow(10, digits || 0);
var temp = Math.trunc(step * n);
return temp / step;
}
[ truncate(5.467,2),
truncate(985.943,2),
truncate(17.56,2),
truncate(0, 1),
truncate(1.11, 1) + 22];
The first method is "99.92% slower" than the second, so the second is definitely the one I would recommend using.
Okay, back to finding other ways to avoid work...
I found a problem: considering the next situation: 2.1 or 1.2 or -6.4
What if you want always 3 decimals or two or wharever, so, you have to complete the leading zeros to the right
// 3 decimals numbers
0.5 => 0.500
// 6 decimals
0.1 => 0.10000
// 4 decimales
-2.1 => -2.1000
// truncate to 3 decimals
3.11568 => 3.115
This is the fixed function of Nick Knowlson
function truncateDecimals (num, digits)
{
var numS = num.toString();
var decPos = numS.indexOf('.');
var substrLength = decPos == -1 ? numS.length : 1 + decPos + digits;
var trimmedResult = numS.substr(0, substrLength);
var finalResult = isNaN(trimmedResult) ? 0 : trimmedResult;
// adds leading zeros to the right
if (decPos != -1){
var s = trimmedResult+"";
decPos = s.indexOf('.');
var decLength = s.length - decPos;
while (decLength <= digits){
s = s + "0";
decPos = s.indexOf('.');
decLength = s.length - decPos;
substrLength = decPos == -1 ? s.length : 1 + decPos + digits;
};
finalResult = s;
}
return finalResult;
};
https://jsfiddle.net/huttn155/7/
function toFixed(number, digits) {
var reg_ex = new RegExp("(\\d+\\.\\d{" + digits + "})(\\d)")
var array = number.toString().match(reg_ex);
return array ? parseFloat(array[1]) : number.valueOf()
}
var test = 10.123456789
var __fixed = toFixed(test, 6)
console.log(__fixed)
// => 10.123456
The answer by #kirilloid seems to be the correct answer, however, the main code needs to be updated. His solution doesn't take care of negative numbers (which someone did mention in the comment section but has not been updated in the main code).
Updating that to a complete final tested solution:
Number.prototype.toFixedDown = function(digits) {
var re = new RegExp("([-]*\\d+\\.\\d{" + digits + "})(\\d)"),
m = this.toString().match(re);
return m ? parseFloat(m[1]) : this.valueOf();
};
Sample Usage:
var x = 3.1415629;
Logger.log(x.toFixedDown(2)); //or use whatever you use to log
Fiddle: JS Number Round down
PS: Not enough repo to comment on that solution.
Here my take on the subject:
convert.truncate = function(value, decimals) {
decimals = (decimals === undefined ? 0 : decimals);
return parseFloat((value-(0.5/Math.pow(10, decimals))).toFixed(decimals),10);
};
It's just a slightly more elaborate version of
(f - 0.005).toFixed(2)
Here is simple but working function to truncate number upto 2 decimal places.
function truncateNumber(num) {
var num1 = "";
var num2 = "";
var num1 = num.split('.')[0];
num2 = num.split('.')[1];
var decimalNum = num2.substring(0, 2);
var strNum = num1 +"."+ decimalNum;
var finalNum = parseFloat(strNum);
return finalNum;
}
The resulting type remains a number...
/* Return the truncation of n wrt base */
var trunc = function(n, base) {
n = (n / base) | 0;
return base * n;
};
var t = trunc(5.467, 0.01);
Lodash has a few Math utility methods that can round, floor, and ceil a number to a given decimal precision. This leaves off trailing zeroes.
They take an interesting approach, using the exponent of a number. Apparently this avoids rounding issues.
(Note: func is Math.round or ceil or floor in the code below)
// Shift with exponential notation to avoid floating-point issues.
var pair = (toString(number) + 'e').split('e'),
value = func(pair[0] + 'e' + (+pair[1] + precision));
pair = (toString(value) + 'e').split('e');
return +(pair[0] + 'e' + (+pair[1] - precision));
Link to the source code
const TO_FIXED_MAX = 100;
function truncate(number, decimalsPrecison) {
// make it a string with precision 1e-100
number = number.toFixed(TO_FIXED_MAX);
// chop off uneccessary digits
const dotIndex = number.indexOf('.');
number = number.substring(0, dotIndex + decimalsPrecison + 1);
// back to a number data type (app specific)
return Number.parseFloat(number);
}
// example
truncate(0.00000001999, 8);
0.00000001
works with:
negative numbers
very small numbers (Number.EPSILON precision)
The one that is mark as the solution is the better solution I been found until today, but has a serious problem with 0 (for example, 0.toFixedDown(2) gives -0.01). So I suggest to use this:
Number.prototype.toFixedDown = function(digits) {
if(this == 0) {
return 0;
}
var n = this - Math.pow(10, -digits)/2;
n += n / Math.pow(2, 53); // added 1360765523: 17.56.toFixedDown(2) === "17.56"
return n.toFixed(digits);
}
Here is what I use:
var t = 1;
for (var i = 0; i < decimalPrecision; i++)
t = t * 10;
var f = parseFloat(value);
return (Math.floor(f * t)) / t;
You can work with strings.
It Checks if '.' exists, and then removes part of string.
truncate (7.88, 1) --> 7.8
truncate (7.889, 2) --> 7.89
truncate (-7.88, 1 ) --> -7.88
function truncate(number, decimals) {
const tmp = number + '';
if (tmp.indexOf('.') > -1) {
return +tmp.substr(0 , tmp.indexOf('.') + decimals+1 );
} else {
return +number
}
}
function trunc(num, dec) {
const pow = 10 ** dec
return Math.trunc(num * pow) / pow
}
// ex.
trunc(4.9634, 1) // 4.9
trunc(4.9634, 2) // 4.96
trunc(-4.9634, 1) // -4.9
You can use toFixed(2) to convert your float to a string with 2 decimal points. Then you can wrap that in floatParse() to convert that string back to a float to make it usable for calculations or db storage.
const truncatedNumber = floatParse(num.toFixed(2))
I am not sure of the potential drawbacks of this answer like increased processing time but I tested edge cases from other comments like .29 which returns .29 (not .28 like other solutions). It also handles negative numbers.
just to point out a simple solution that worked for me
convert it to string and then regex it...
var number = 123.45678;
var number_s = '' + number;
var number_truncated_s = number_s.match(/\d*\.\d{4}/)[0]
var number_truncated = parseFloat(number_truncated_s)
It can be abbreviated to
var number_truncated = parseFloat(('' + 123.4568908).match(/\d*\.\d{4}/)[0])
Here is an ES6 code which does what you want
const truncateTo = (unRouned, nrOfDecimals = 2) => {
const parts = String(unRouned).split(".");
if (parts.length !== 2) {
// without any decimal part
return unRouned;
}
const newDecimals = parts[1].slice(0, nrOfDecimals),
newString = `${parts[0]}.${newDecimals}`;
return Number(newString);
};
// your examples
console.log(truncateTo(5.467)); // ---> 5.46
console.log(truncateTo(985.943)); // ---> 985.94
// other examples
console.log(truncateTo(5)); // ---> 5
console.log(truncateTo(-5)); // ---> -5
console.log(truncateTo(-985.943)); // ---> -985.94
Suppose you want to truncate number x till n digits.
Math.trunc(x * pow(10,n))/pow(10,n);
Number.prototype.truncate = function(places) {
var shift = Math.pow(10, places);
return Math.trunc(this * shift) / shift;
};

Get decimal portion of a number with JavaScript

I have float numbers like 3.2 and 1.6.
I need to separate the number into the integer and decimal part. For example, a value of 3.2 would be split into two numbers, i.e. 3 and 0.2
Getting the integer portion is easy:
n = Math.floor(n);
But I am having trouble getting the decimal portion.
I have tried this:
remainder = n % 2; //obtem a parte decimal do rating
But it does not always work correctly.
The previous code has the following output:
n = 3.1 // gives remainder = 1.1
What I am missing here?
Use 1, not 2.
js> 2.3 % 1
0.2999999999999998
var decimal = n - Math.floor(n)
Although this won't work for minus numbers so we might have to do
n = Math.abs(n); // Change to positive
var decimal = n - Math.floor(n)
You could convert to string, right?
n = (n + "").split(".");
How is 0.2999999999999998 an acceptable answer? If I were the asker I would want an answer of .3. What we have here is false precision, and my experiments with floor, %, etc indicate that Javascript is fond of false precision for these operations. So I think the answers that are using conversion to string are on the right track.
I would do this:
var decPart = (n+"").split(".")[1];
Specifically, I was using 100233.1 and I wanted the answer ".1".
Here's how I do it, which I think is the most straightforward way to do it:
var x = 3.2;
int_part = Math.trunc(x); // returns 3
float_part = Number((x-int_part).toFixed(2)); // return 0.2
A simple way of doing it is:
var x = 3.2;
var decimals = x - Math.floor(x);
console.log(decimals); //Returns 0.20000000000000018
Unfortunately, that doesn't return the exact value. However, that is easily fixed:
var x = 3.2;
var decimals = x - Math.floor(x);
console.log(decimals.toFixed(1)); //Returns 0.2
You can use this if you don't know the number of decimal places:
var x = 3.2;
var decimals = x - Math.floor(x);
var decimalPlaces = x.toString().split('.')[1].length;
decimals = decimals.toFixed(decimalPlaces);
console.log(decimals); //Returns 0.2
Language independent way:
var a = 3.2;
var fract = a * 10 % 10 /10; //0.2
var integr = a - fract; //3
note that it correct only for numbers with one fractioanal lenght )
You can use parseInt() function to get the integer part than use that to extract the decimal part
var myNumber = 3.2;
var integerPart = parseInt(myNumber);
var decimalPart = myNumber - integerPart;
Or you could use regex like:
splitFloat = function(n){
const regex = /(\d*)[.,]{1}(\d*)/;
var m;
if ((m = regex.exec(n.toString())) !== null) {
return {
integer:parseInt(m[1]),
decimal:parseFloat(`0.${m[2]}`)
}
}
}
The following works regardless of the regional settings for decimal separator... on the condition only one character is used for a separator.
var n = 2015.15;
var integer = Math.floor(n).toString();
var strungNumber = n.toString();
if (integer.length === strungNumber.length)
return "0";
return strungNumber.substring(integer.length + 1);
It ain't pretty, but it's accurate.
If precision matters and you require consistent results, here are a few propositions that will return the decimal part of any number as a string, including the leading "0.". If you need it as a float, just add var f = parseFloat( result ) in the end.
If the decimal part equals zero, "0.0" will be returned. Null, NaN and undefined numbers are not tested.
1. String.split
var nstring = (n + ""),
narray = nstring.split("."),
result = "0." + ( narray.length > 1 ? narray[1] : "0" );
2. String.substring, String.indexOf
var nstring = (n + ""),
nindex = nstring.indexOf("."),
result = "0." + (nindex > -1 ? nstring.substring(nindex + 1) : "0");
3. Math.floor, Number.toFixed, String.indexOf
var nstring = (n + ""),
nindex = nstring.indexOf("."),
result = ( nindex > -1 ? (n - Math.floor(n)).toFixed(nstring.length - nindex - 1) : "0.0");
4. Math.floor, Number.toFixed, String.split
var nstring = (n + ""),
narray = nstring.split("."),
result = (narray.length > 1 ? (n - Math.floor(n)).toFixed(narray[1].length) : "0.0");
Here is a jsPerf link: https://jsperf.com/decpart-of-number/
We can see that proposition #2 is the fastest.
A good option is to transform the number into a string and then split it.
// Decimal number
let number = 3.2;
// Convert it into a string
let string = number.toString();
// Split the dot
let array = string.split('.');
// Get both numbers
// The '+' sign transforms the string into a number again
let firstNumber = +array[0]; // 3
let secondNumber = +array[1]; // 2
In one line of code
let [firstNumber, secondNumber] = [+number.toString().split('.')[0], +number.toString().split('.')[1]];
Depending the usage you will give afterwards, but this simple solution could also help you.
Im not saying its a good solution, but for some concrete cases works
var a = 10.2
var c = a.toString().split(".")
console.log(c[1] == 2) //True
console.log(c[1] === 2) //False
But it will take longer than the proposed solution by #Brian M. Hunt
(2.3 % 1).toFixed(4)
I am using:
var n = -556.123444444;
var str = n.toString();
var decimalOnly = 0;
if( str.indexOf('.') != -1 ){ //check if has decimal
var decimalOnly = parseFloat(Math.abs(n).toString().split('.')[1]);
}
Input: -556.123444444
Result: 123444444
You could convert it to a string and use the replace method to replace the integer part with zero, then convert the result back to a number :
var number = 123.123812,
decimals = +number.toString().replace(/^[^\.]+/,'0');
n = Math.floor(x);
remainder = x % 1;
Math functions are faster, but always returns not native expected values.
Easiest way that i found is
(3.2+'').replace(/^[-\d]+\./, '')
The best way to avoid mathematical imprecision is to convert to a string, but ensure that it is in the "dot" format you expect by using toLocaleString:
function getDecimals(n) {
// Note that maximumSignificantDigits defaults to 3 so your decimals will be rounded if not changed.
const parts = n.toLocaleString('en-US', { maximumSignificantDigits: 18 }).split('.')
return parts.length > 1 ? Number('0.' + parts[1]) : 0
}
console.log(getDecimals(10.58))
You can simply use parseInt() function to help, example:
let decimal = 3.2;
let remainder = decimal - parseInt(decimal);
document.write(remainder);
I had a case where I knew all the numbers in question would have only one decimal and wanted to get the decimal portion as an integer so I ended up using this kind of approach:
var number = 3.1,
decimalAsInt = Math.round((number - parseInt(number)) * 10); // returns 1
This works nicely also with integers, returning 0 in those cases.
Although I am very late to answer this, please have a look at the code.
let floatValue = 3.267848;
let decimalDigits = floatValue.toString().split('.')[1];
let decimalPlaces = decimalDigits.length;
let decimalDivider = Math.pow(10, decimalPlaces);
let fractionValue = decimalDigits/decimalDivider;
let integerValue = floatValue - fractionValue;
console.log("Float value: "+floatValue);
console.log("Integer value: "+integerValue);
console.log("Fraction value: "+fractionValue)
I like this answer https://stackoverflow.com/a/4512317/1818723 just need to apply float point fix
function fpFix(n) {
return Math.round(n * 100000000) / 100000000;
}
let decimalPart = 2.3 % 1; //0.2999999999999998
let correct = fpFix(decimalPart); //0.3
Complete function handling negative and positive
function getDecimalPart(decNum) {
return Math.round((decNum % 1) * 100000000) / 100000000;
}
console.log(getDecimalPart(2.3)); // 0.3
console.log(getDecimalPart(-2.3)); // -0.3
console.log(getDecimalPart(2.17247436)); // 0.17247436
P.S. If you are cryptocurrency trading platform developer or banking system developer or any JS developer ;) please apply fpFix everywhere. Thanks!
2021 Update
Optimized version that tackles precision (or not).
// Global variables.
const DEFAULT_PRECISION = 16;
const MAX_CACHED_PRECISION = 20;
// Helper function to avoid numerical imprecision from Math.pow(10, x).
const _pow10 = p => parseFloat(`1e+${p}`);
// Cache precision coefficients, up to a precision of 20 decimal digits.
const PRECISION_COEFS = new Array(MAX_CACHED_PRECISION);
for (let i = 0; i !== MAX_CACHED_PRECISION; ++i) {
PRECISION_COEFS[i] = _pow10(i);
}
// Function to get a power of 10 coefficient,
// optimized for both speed and precision.
const pow10 = p => PRECISION_COEFS[p] || _pow10(p);
// Function to trunc a positive number, optimized for speed.
// See: https://stackoverflow.com/questions/38702724/math-floor-vs-math-trunc-javascript
const trunc = v => (v < 1e8 && ~~v) || Math.trunc(v);
// Helper function to get the decimal part when the number is positive,
// optimized for speed.
// Note: caching 1 / c or 1e-precision still leads to numerical errors.
// So we have to pay the price of the division by c.
const _getDecimals = (v = 0, precision = DEFAULT_PRECISION) => {
const c = pow10(precision); // Get precision coef.
const i = trunc(v); // Get integer.
const d = v - i; // Get decimal.
return Math.round(d * c) / c;
}
// Augmenting Number proto.
Number.prototype.getDecimals = function(precision) {
return (isFinite(this) && (precision ? (
(this < 0 && -_getDecimals(-this, precision))
|| _getDecimals(this, precision)
) : this % 1)) || 0;
}
// Independent function.
const getDecimals = (input, precision) => (isFinite(input) && (
precision ? (
(this < 0 && -_getDecimals(-this, precision))
|| _getDecimals(this, precision)
) : this % 1
)) || 0;
// Tests:
const test = (value, precision) => (
console.log(value, '|', precision, '-->', value.getDecimals(precision))
);
test(1.001 % 1); // --> 0.0009999999999998899
test(1.001 % 1, 16); // --> 0.000999999999999
test(1.001 % 1, 15); // --> 0.001
test(1.001 % 1, 3); // --> 0.001
test(1.001 % 1, 2); // --> 0
test(-1.001 % 1, 16); // --> -0.000999999999999
test(-1.001 % 1, 15); // --> -0.001
test(-1.001 % 1, 3); // --> -0.001
test(-1.001 % 1, 2); // --> 0
After looking at several of these, I am now using...
var rtnValue = Number(7.23);
var tempDec = ((rtnValue / 1) - Math.floor(rtnValue)).toFixed(2);
Floating-point decimal sign and number format can be dependent from country (.,), so independent solution, which preserved floating point part, is:
getFloatDecimalPortion = function(x) {
x = Math.abs(parseFloat(x));
let n = parseInt(x);
return Number((x - n).toFixed(Math.abs((""+x).length - (""+n).length - 1)));
}
– it is internationalized solution, instead of location-dependent:
getFloatDecimalPortion = x => parseFloat("0." + ((x + "").split(".")[1]));
Solution desription step by step:
parseFloat() for guaranteeing input cocrrection
Math.abs() for avoiding problems with negative numbers
n = parseInt(x) for getting decimal part
x - n for substracting decimal part
We have now number with zero decimal part, but JavaScript could give us additional floating part digits, which we do not want
So, limit additional digits by calling toFixed() with count of digits in floating part of original float number x. Count is calculated as difference between length of original number x and number n in their string representation.
This function splits float number into integers and returns it in array:
function splitNumber(num)
{
num = (""+num).match(/^(-?[0-9]+)([,.][0-9]+)?/)||[];
return [ ~~num[1], +(0+num[2])||0 ];
}
console.log(splitNumber(3.02)); // [ 3, 0.2 ]
console.log(splitNumber(123.456)); // [ 123, 0.456 ]
console.log(splitNumber(789)); // [ 789, 0 ]
console.log(splitNumber(-2.7)); // [ -2, 0.7 ]
console.log(splitNumber("test")); // [ 0, 0 ]
You can extend it to only return existing numbers and null if no number exists:
function splitNumber(num)
{
num = (""+num).match(/^(-?[0-9]+)([,.][0-9]+)?/);
return [ num ? ~~num[1] : null, num && num[2] ? +(0 + num[2]) : null ];
}
console.log(splitNumber(3.02)); // [ 3, 0.02 ]
console.log(splitNumber(123.456)); // [ 123, 0.456 ]
console.log(splitNumber(789)); // [ 789, null ]
console.log(splitNumber(-2.7)); // [ -2, 0.7 ]
console.log(splitNumber("test")); // [ null, null ]
You can also truncate the number
function decimals(val) {
const valStr = val.toString();
const valTruncLength = String(Math.trunc(val)).length;
const dec =
valStr.length != valTruncLength
? valStr.substring(valTruncLength + 1)
: "";
return dec;
}
console.log("decimals: ", decimals(123.654321));
console.log("no decimals: ", decimals(123));
The following function will return an array which will have 2 elements. The first element will be the integer part and the second element will be the decimal part.
function splitNum(num) {
num = num.toString().split('.')
num[0] = Number(num[0])
if (num[1]) num[1] = Number('0.' + num[1])
else num[1] = 0
return num
}
//call this function like this
let num = splitNum(3.2)
console.log(`Integer part is ${num[0]}`)
console.log(`Decimal part is ${num[1]}`)
//or you can call it like this
let [int, deci] = splitNum(3.2)
console.log('Intiger part is ' + int)
console.log('Decimal part is ' + deci)
For example for add two numbers
function add(number1, number2) {
let decimal1 = String(number1).substring(String(number1).indexOf(".") + 1).length;
let decimal2 = String(number2).substring(String(number2).indexOf(".") + 1).length;
let z = Math.max(decimal1, decimal2);
return (number1 * Math.pow(10, z) + number2 * Math.pow(10, z)) / Math.pow(10, z);
}
float a=3.2;
int b=(int)a; // you'll get output b=3 here;
int c=(int)a-b; // you'll get c=.2 value here

Categories

Resources