In JavaScript, when converting from a float to a string, how can I get just 2 digits after the decimal point? For example, 0.34 instead of 0.3445434.
-
22Just some nit-picking: do you want to 'chop off' all but the two first digits, or do you want to round to two digits?xtofl– xtofl2009年03月19日 09:45:07 +00:00Commented Mar 19, 2009 at 9:45
16 Answers 16
There are functions to round numbers. For example:
var x = 5.0364342423;
print(x.toFixed(2));
will print 5.04.
EDIT: Fiddle
-
13I would recommend against using print() in a browser thoughcobbal– cobbal2009年03月19日 09:45:14 +00:00Commented Mar 19, 2009 at 9:45
-
90Be careful about this, toFixed() returns a string:
var x = 5.036432346; var y = x.toFixed(2) + 100;
y
will be equal"5.03100"
Vlad– Vlad2012年10月04日 04:16:38 +00:00Commented Oct 4, 2012 at 4:16 -
5Be aware that (1e100).toFixed(2) === "1e+100"qbolec– qbolec2014年02月15日 16:18:49 +00:00Commented Feb 15, 2014 at 16:18
-
9Also, beware of inconsistent rounding :
(0.335).toFixed(2) == 0.34 == (0.345).toFixed(2)
...Skippy le Grand Gourou– Skippy le Grand Gourou2015年08月10日 16:12:15 +00:00Commented Aug 10, 2015 at 16:12 -
11If you search for an equivalent of toFixed but with consistent rounding, use toLocaleString : (0.345).toLocaleString('en-EN',{minimumFractionDigits:2, maximumFractionDigits:2})fred727– fred7272018年08月29日 07:55:47 +00:00Commented Aug 29, 2018 at 7:55
var result = Math.round(original*100)/100;
The specifics, in case the code isn't self-explanatory.
edit: ...or just use toFixed
, as proposed by Tim Büthe. Forgot that one, thanks (and an upvote) for reminder :)
-
1I was using this in library "Highchart" where it doesn't accepts string values hence toFixed didn't worked for me, Math.round solved my issue, thanksSwapnil Chincholkar– Swapnil Chincholkar2015年06月23日 13:11:40 +00:00Commented Jun 23, 2015 at 13:11
-
6
toFixed()
will mimic what something likeprintf()
does in C. However,toFixed()
andMath.round()
will handle rounding differently. In this case,toFixed()
will have the same sort of effectMath.floor()
would have (granted you're multiplying the original by 10^n beforehand, and callingtoFixed()
with n digits). The "correctness" of the answer is very dependent on what the OP wants here, and both are "correct" in their own way.DDPWNAGE– DDPWNAGE2018年04月17日 05:31:42 +00:00Commented Apr 17, 2018 at 5:31 -
2The method proposed here is unfortunately not a good one, because it can result into unexpected values like 4.99999999998 etc, because of how binary base works. Please use toFixed instead.Karveiani– Karveiani2020年10月18日 00:37:42 +00:00Commented Oct 18, 2020 at 0:37
Be careful when using toFixed()
:
First, rounding the number is done using the binary representation of the number, which might lead to unexpected behaviour. For example
(0.595).toFixed(2) === '0.59'
instead of '0.6'
.
Second, there's an IE bug with toFixed()
. In IE (at least up to version 7, didn't check IE8), the following holds true:
(0.9).toFixed(0) === '0'
It might be a good idea to follow kkyy's suggestion or to use a custom toFixed()
function, eg
function toFixed(value, precision) {
var power = Math.pow(10, precision || 0);
return String(Math.round(value * power) / power);
}
-
Yes, this can be very important when creating code to predict prices. Thanks! +1Fabio Milheiro– Fabio Milheiro2010年10月07日 15:39:14 +00:00Commented Oct 7, 2010 at 15:39
-
13I would suggest adding the native
.toFixed()
method in the return value, which will add the required amount of precision, eg:return (Math.round(value * power) / power).toFixed(precision);
and also return the value as a string. Otherwise, precision of 20 is ignored for smaller decimalsWilliam Joss Crowcroft– William Joss Crowcroft2011年08月22日 17:33:24 +00:00Commented Aug 22, 2011 at 17:33 -
3One note regarding
toFixed
: note that increasing the precision can yield unexpected results:(1.2).toFixed(16) === "1.2000000000000000"
, while(1.2).toFixed(17) === "1.19999999999999996"
(in Firefox/Chrome; in IE8 the latter doesn't hold due to lower precision that IE8 can offer internally).jakub.g– jakub.g2013年05月13日 08:54:57 +00:00Commented May 13, 2013 at 8:54 -
2Please note that even
(0.598).toFixed(2)
does not produce0.6
. It produces0.60
:)qbolec– qbolec2015年03月25日 07:14:15 +00:00Commented Mar 25, 2015 at 7:14 -
1Also, beware of inconstistent rounding :
(0.335).toFixed(2) == 0.34 == (0.345).toFixed(2)
.Skippy le Grand Gourou– Skippy le Grand Gourou2015年08月10日 16:14:09 +00:00Commented Aug 10, 2015 at 16:14
One more problem to be aware of, is that toFixed()
can produce unnecessary zeros at the end of the number.
For example:
var x=(23-7.37)
x
15.629999999999999
x.toFixed(6)
"15.630000"
The idea is to clean up the output using a RegExp
:
function humanize(x){
return x.toFixed(6).replace(/\.?0*$/,'');
}
The RegExp
matches the trailing zeros (and optionally the decimal point) to make sure it looks good for integers as well.
humanize(23-7.37)
"15.63"
humanize(1200)
"1200"
humanize(1200.03)
"1200.03"
humanize(3/4)
"0.75"
humanize(4/3)
"1.333333"
-
Number.prototype.minFixed = function(decimals) { return this.toFixed(decimals).replace(/\.?0*$/, ""); }Luc Bloom– Luc Bloom2018年01月31日 22:43:44 +00:00Commented Jan 31, 2018 at 22:43
-
This should be acepted, trailing zeros are annoying, I was looking exactly for this solution, gj.exoslav– exoslav2018年06月06日 08:19:40 +00:00Commented Jun 6, 2018 at 8:19
-
3Trailing zeros may be annoying, but this is exactly what the method name "toFixed" promises to do ;)ksadowski– ksadowski2019年07月10日 11:48:38 +00:00Commented Jul 10, 2019 at 11:48
var x = 0.3445434
x = Math.round (x*100) / 100 // this will make nice rounding
-
Math.round(1.015 * 100) / 100 gives 1.01 while we would expect it to be 1.02 ?gaurav5430– gaurav54302019年12月26日 05:05:45 +00:00Commented Dec 26, 2019 at 5:05
-
console.log(Math.round((1.015 + 0.00001) * 100) / 100) // 1.02 this would solve the above caseMonish N– Monish N2021年09月13日 10:20:34 +00:00Commented Sep 13, 2021 at 10:20
Another possibility is to use toLocaleString()
function:
The
toLocaleString()
method returns a string with a language-sensitive representation of this number.
const n = 2048.345;
const str = n.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2});
console.log(str);
-
1Works great; solves the rounding inconsistency that exists for
toFixed
, at least for the case shown in this thread. (of(0.345).toFixed(2)
incorrectly returning0.34
) [might be worth specifyingen-US
oren-GB
as the local specifically though, in case the user's locale theoretically has a weird/unexpected rounding rule]Venryx– Venryx2024年07月14日 21:50:32 +00:00Commented Jul 14, 2024 at 21:50 -
1Oh something to keep in mind though: I've tested the speed of
toLocaleString
, and it is much slower thantoFixed
(8000 calls takes ~270ms rather than ~2ms). So I'm actually going withtoFixed
instead, and just increasing the precision enough that any inconsistent rounding it has on the last digit doesn't matter for any of my usages.Venryx– Venryx2024年07月14日 22:13:01 +00:00Commented Jul 14, 2024 at 22:13
The key here I guess is to round up correctly first, then you can convert it to String.
function roundOf(n, p) {
const n1 = n * Math.pow(10, p + 1);
const n2 = Math.floor(n1 / 10);
if (n1 >= (n2 * 10 + 5)) {
return (n2 + 1) / Math.pow(10, p);
}
return n2 / Math.pow(10, p);
}
// All edge cases listed in this thread
roundOf(95.345, 2); // 95.35
roundOf(95.344, 2); // 95.34
roundOf(5.0364342423, 2); // 5.04
roundOf(0.595, 2); // 0.60
roundOf(0.335, 2); // 0.34
roundOf(0.345, 2); // 0.35
roundOf(551.175, 2); // 551.18
roundOf(0.3445434, 2); // 0.34
Now you can safely format this value with toFixed(p). So with your specific case:
roundOf(0.3445434, 2).toFixed(2); // 0.34
-
.toFixed(2) converts a number into a string, rounding the number to keep only two decimalsDan Alboteanu– Dan Alboteanu2020年11月19日 09:19:14 +00:00Commented Nov 19, 2020 at 9:19
There is a problem with all those solutions floating around using multipliers. Both kkyy and Christoph's solutions are wrong unfortunately.
Please test your code for number 551.175 with 2 decimal places - it will round to 551.17 while it should be 551.18 ! But if you test for ex. 451.175 it will be ok - 451.18. So it's difficult to spot this error at a first glance.
The problem is with multiplying: try 551.175 * 100 = 55117.49999999999 (ups!)
So my idea is to treat it with toFixed() before using Math.round();
function roundFix(number, precision)
{
var multi = Math.pow(10, precision);
return Math.round( (number * multi).toFixed(precision + 1) ) / multi;
}
-
2That's the problem with arithmetic in js: (551.175 * 10 * 10) !== (551.175 * 100). You have to use decimal increments to move the comma for non real decimal results.Kir Kanos– Kir Kanos2014年03月31日 15:55:49 +00:00Commented Mar 31, 2014 at 15:55
-
+1 for noticing this, however
toFixed
is affected as well —(0.335).toFixed(2) == 0.34 == (0.345).toFixed(2)
... Whichever method is used, better add an epsilon before the rounding.Skippy le Grand Gourou– Skippy le Grand Gourou2015年08月10日 15:56:32 +00:00Commented Aug 10, 2015 at 15:56
If you want the string without round you can use this RegEx (maybe is not the most efficient way... but is really easy)
(2.34567778).toString().match(/\d+\.\d{2}/)[0]
// '2.34'
function trimNumber(num, len) {
const modulu_one = 1;
const start_numbers_float=2;
var int_part = Math.trunc(num);
var float_part = String(num % modulu_one);
float_part = float_part.slice(start_numbers_float, start_numbers_float+len);
return int_part+'.'+float_part;
}
-
great answer except that you are missing semicolons ( No, in es6 semicolons are not obsolete and we still have to use them in some cases). I had to also edit last row to:
return float_part ? int_part+'.'+float_part : int_part;
otherwise if you passed Integer, it returned number with a dot at the end (example input:2100
, output:2100.
)Kuba Šimonovský– Kuba Šimonovský2017年10月03日 10:24:31 +00:00Commented Oct 3, 2017 at 10:24
There is no way to avoid inconsistent rounding for prices with x.xx5 as actual value using either multiplication or division. If you need to calculate correct prices client-side you should keep all amounts in cents. This is due to the nature of the internal representation of numeric values in JavaScript. Notice that Excel suffers from the same problems so most people wouldn't notice the small errors caused by this phenomen. However errors may accumulate whenever you add up a lot of calculated values, there is a whole theory around this involving the order of calculations and other methods to minimize the error in the final result. To emphasize on the problems with decimal values, please note that 0.1 + 0.2 is not exactly equal to 0.3 in JavaScript, while 1 + 2 is equal to 3.
-
the solution would be to separate entire part and decimal part, and represent them as integers in base 10, instead of using floats, here it works without problem for prettyPrint, but in general you have to choose between a base and another, a represention for real numbers and another, each has its problemsreuns– reuns2015年11月06日 18:54:30 +00:00Commented Nov 6, 2015 at 18:54
-
"Excel suffers from the same problems". source ?gaurav5430– gaurav54302019年12月26日 05:07:05 +00:00Commented Dec 26, 2019 at 5:07
Maybe you'll also want decimal separator? Here is a function I just made:
function formatFloat(num,casasDec,sepDecimal,sepMilhar) {
if (num < 0)
{
num = -num;
sinal = -1;
} else
sinal = 1;
var resposta = "";
var part = "";
if (num != Math.floor(num)) // decimal values present
{
part = Math.round((num-Math.floor(num))*Math.pow(10,casasDec)).toString(); // transforms decimal part into integer (rounded)
while (part.length < casasDec)
part = '0'+part;
if (casasDec > 0)
{
resposta = sepDecimal+part;
num = Math.floor(num);
} else
num = Math.round(num);
} // end of decimal part
while (num > 0) // integer part
{
part = (num - Math.floor(num/1000)*1000).toString(); // part = three less significant digits
num = Math.floor(num/1000);
if (num > 0)
while (part.length < 3) // 123.023.123 if sepMilhar = '.'
part = '0'+part; // 023
resposta = part+resposta;
if (num > 0)
resposta = sepMilhar+resposta;
}
if (sinal < 0)
resposta = '-'+resposta;
return resposta;
}
/** don't spend 5 minutes, use my code **/
function prettyFloat(x,nbDec) {
if (!nbDec) nbDec = 100;
var a = Math.abs(x);
var e = Math.floor(a);
var d = Math.round((a-e)*nbDec); if (d == nbDec) { d=0; e++; }
var signStr = (x<0) ? "-" : " ";
var decStr = d.toString(); var tmp = 10; while(tmp<nbDec && d*tmp < nbDec) {decStr = "0"+decStr; tmp*=10;}
var eStr = e.toString();
return signStr+eStr+"."+decStr;
}
prettyFloat(0); // "0.00"
prettyFloat(-1); // "-1.00"
prettyFloat(-0.999); // "-1.00"
prettyFloat(0.5); // "0.50"
I use this code to format floats. It is based on toPrecision()
but it strips unnecessary zeros. I would welcome suggestions for how to simplify the regex.
function round(x, n) {
var exp = Math.pow(10, n);
return Math.floor(x*exp + 0.5)/exp;
}
Usage example:
function test(x, n, d) {
var rounded = rnd(x, d);
var result = rounded.toPrecision(n);
result = result.replace(/\.?0*$/, '');
result = result.replace(/\.?0*e/, 'e');
result = result.replace('e+', 'e');
return result;
}
document.write(test(1.2000e45, 3, 2) + '=' + '1.2e45' + '<br>');
document.write(test(1.2000e+45, 3, 2) + '=' + '1.2e45' + '<br>');
document.write(test(1.2340e45, 3, 2) + '=' + '1.23e45' + '<br>');
document.write(test(1.2350e45, 3, 2) + '=' + '1.24e45' + '<br>');
document.write(test(1.0000, 3, 2) + '=' + '1' + '<br>');
document.write(test(1.0100, 3, 2) + '=' + '1.01' + '<br>');
document.write(test(1.2340, 4, 2) + '=' + '1.23' + '<br>');
document.write(test(1.2350, 4, 2) + '=' + '1.24' + '<br>');
countDecimals = value => {
if (Math.floor(value) === value) return 0;
let stringValue = value.toString().split(".")[1];
if (stringValue) {
return value.toString().split(".")[1].length
? value.toString().split(".")[1].length
: 0;
} else {
return 0;
}
};
formatNumber=(ans)=>{
let decimalPlaces = this.countDecimals(ans);
ans = 1 * ans;
if (decimalPlaces !== 0) {
let onePlusAns = ans + 1;
let decimalOnePlus = this.countDecimals(onePlusAns);
if (decimalOnePlus < decimalPlaces) {
ans = ans.toFixed(decimalPlaces - 1).replace(/\.?0*$/, "");
} else {
let tenMulAns = ans * 10;
let decimalTenMul = this.countDecimals(tenMulAns);
if (decimalTenMul + 1 < decimalPlaces) {
ans = ans.toFixed(decimalPlaces - 1).replace(/\.?0*$/, "");
}
}
}
}
I just add 1 to the value and count the decimal digits present in the original value and the added value. If I find the decimal digits after adding one less than the original decimal digits, I just call the toFixed() with (original decimals - 1). I also check by multiplying the original value by 10 and follow the same logic in case adding one doesn't reduce redundant decimal places. A simple workaround to handle floating-point number rounding in JS. Works in most cases I tried.
const float = 0.3445434; // number
const fix = 2; // number
function fn(float: number, fix: number) {
return parseFloat(float.toFixed(fix));
}
const newFloat = fn(float, fix);
console.log(newFloat);
Although the topic is float point, JavaScript's parseFloat method is not referenced. An important detail.
After using toFixed method, make sure to change your value type back to number type. See parseFloat
References: https://developer.mozilla.org/