F40
F40

Reputation:

How to format a float in javascript?

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.

Upvotes: 512

Views: 613931

Answers (16)

Christoph
Christoph

Reputation: 169831

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);
}

Upvotes: 201

umutyerebakmaz
umutyerebakmaz

Reputation: 1037

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/

Upvotes: 0

Wtower
Wtower

Reputation: 19922

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

Upvotes: 10

Silent Wraith
Silent Wraith

Reputation: 1

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.

Upvotes: 0

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'

Upvotes: 4

Steven
Steven

Reputation: 101

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

Upvotes: 10

Mark
Mark

Reputation: 1

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>');

Upvotes: 0

ofir_aghai
ofir_aghai

Reputation: 3321

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;
}

Upvotes: 2

qbolec
qbolec

Reputation: 5134

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"

Upvotes: 54

kkyy
kkyy

Reputation: 12470

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

Upvotes: 260

reuns
reuns

Reputation: 894

/** 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"

Upvotes: 0

Dony
Dony

Reputation: 11

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.

Upvotes: 1

ArteQ
ArteQ

Reputation: 79

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;
}

Upvotes: 6

Tim B&#252;the
Tim B&#252;the

Reputation: 63814

There are functions to round numbers. For example:

var x = 5.0364342423;
print(x.toFixed(2));

will print 5.04.

EDIT: Fiddle

Upvotes: 974

Rodrigo
Rodrigo

Reputation: 5139

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;
}

Upvotes: 0

Ilya Birman
Ilya Birman

Reputation: 10102

var x = 0.3445434
x = Math.round (x*100) / 100 // this will make nice rounding

Upvotes: 12

Related Questions