This is "By Design". The parseFloat function will only consider the parts of the string up until in reaches a non +, -, number, exponent or decimal point. Once it sees the comma it stops looking and only considers the "75" portion.

  • https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/parseFloat

To fix this convert the commas to decimal points.

var fullcost = parseFloat($("#fullcost").text().replace(',', '.'));
Answer from JaredPar on Stack Overflow
๐ŸŒ
Reddit
reddit.com โ€บ r/learnjavascript โ€บ parse float and thousand separator
r/learnjavascript on Reddit: Parse Float and thousand separator
May 17, 2021 -

How can I add a thousand separator to a parseFloat value?

For example - if the value is 96645 I would like to show as 96,645.

Thanks for any help

Discussions

Numbers parsed incorrectly if "." is thousands separator, "," decimal separator and decimal part not specified
Description There is a closed issue: #3261, where last comment author is saying that this bug does not appear anymore and provides a JS fiddle: http://jsfiddle.net/z25d4ydm/ She is right that it wo... More on github.com
๐ŸŒ github.com
15
July 12, 2017
Globalize.parseFloat does not consistently parse group and decimal separators
Globalize.culture("pl"); ... // 1234 // assuming a culture where "," is the group separator // and "," is the decimal separator console.log(Globalize.parseFloat("1839,560")); // 1234.56 // assuming a culture where "." is the group separator // and "." is the decimal ... More on github.com
๐ŸŒ github.com
24
October 19, 2011
Function to format numbers with thousand separators and decimals
The value you return will have a 1000 separator in the wrong place if the number length is divisible by 3 eg neat(-100) returns "-.100,00" The rewrite fixes the negative number problem. I added a places variable so that the number of decimal places can be set. Uses default parameters to define defaults for (new places arg), thousandSep ... More on codereview.stackexchange.com
๐ŸŒ codereview.stackexchange.com
April 25, 2019
Thousands separator in jQuery is causing parseFloat to misinterpret numbers
I am using a . as a thousands separator. So the string 128.814 should be read as "one hundred and twenty eight thousand, eight hundred and fourteen". When I add this to the number 900, I want the More on stackoverflow.com
๐ŸŒ stackoverflow.com
June 12, 2015
๐ŸŒ
GitHub
github.com โ€บ handsontable โ€บ handsontable โ€บ issues โ€บ 4396
Numbers parsed incorrectly if "." is thousands separator, "," decimal separator and decimal part not specified ยท Issue #4396 ยท handsontable/handsontable
July 12, 2017 - if (numbro.validate(changes[i][3]) && !isNaN(changes[i][3])) { changes[i][3] = parseFloat( changes[i][3].replace( new RegExp('\\' + delimiters.thousands, 'g'), '', ).replace( delimiters.decimal, '.' ) ); } else { changes[i][3] = numbro().unformat(changes[i][3]) || changes[i][3]; } Specify for your numbro locale . as thousands separator and , as decimal ยท
Author ย  jacob-s-son
๐ŸŒ
EyeHunts
tutorial.eyehunts.com โ€บ home โ€บ javascript parsefloat thousand comma | example code
Javascript parseFloat thousand comma | Example code
December 12, 2022 - If you want parse a number (float number) string with commas thousand separators into a number by removing the commas, and then use the + operator to do the conversion. const num = +'123,456,789'.replace(/,/g, ''); console.log(num) You can do ...
๐ŸŒ
GitHub
github.com โ€บ globalizejs โ€บ globalize โ€บ issues โ€บ 73
Globalize.parseFloat does not consistently parse group and decimal separators ยท Issue #73 ยท globalizejs/globalize
October 19, 2011 - Globalize.culture("pl"); ... // 1234 // assuming a culture where "," is the group separator // and "," is the decimal separator console.log(Globalize.parseFloat("1839,560")); // 1234.56 // assuming a culture where "." is the group separator ...
Author ย  Tuinel
๐ŸŒ
Bobby Hadz
bobbyhadz.com โ€บ blog โ€บ javascript-parse-string-with-comma-to-number
Parse a String with Commas to a Number in JavaScript | bobbyhadz
March 3, 2024 - Copied!function parseToNumber(str) ...oNumber('12,123,456')); // ๐Ÿ‘‰๏ธ 12123456 ยท The function takes a string with commas as thousands separator and parses the string to a number....
Top answer
1 of 2
4

You can use default parameters to automatically assign a value if none is given.

function neat(numToFormat, thousandSep = ".", decimalSep = ",")

You should start by checking if the input is valid, instead of doing it at the end. It would also be better to throw an error, since it's not easy to tell from the result if the formatting succeeded or not.

if (typeof numToFormat == 'number') {
  if(Number.isNaN(numToFormat) || !Number.isFinite(numToFormat)) {
    throw new Error("Invalid number");
  }
}
else if(typeof numToFormat == 'string') {
  if(!/^\d+((,|\.)\d+)?$/.test(numToFormat)) {
    throw new Error("Invalid string");
  }
}
else {
  throw new Error("Can only use number or string");
}

It's not parseFloat() which is imprecise, but the numbers themselves. JavaScript uses IEEE 754, which is 64-bit floating point numbers, with 53 bits used for precision. The number you are testing against is the highest safe integer, which is 2^53-1 and can be gotten from Number.MAX_SAFE_INTEGER. But your result could still be imprecise with numbers this large, since you are not only using integers but also 2 decimal places.

With string inputs you can get around this by not converting it to a number at all. Since the result is also a string, you can keep it a string all the way through. For number inputs you can only work with the precision you've been given. Any imprecision should be handled by the code calling this function beforehand.

You will need to update your parseInput function to avoid parseFloat. Just cut of any extra decimals, or add them if they are missing. If you want to round the number it gets a bit harder, but it's still possible.

Your placeThousands function can be done a little simpler. There are several ways to do it, but I would cut the string into an array of chunks and then join them together. I would also make it easier to change the chunk size by putting it in a variable.

const chunkSize = 3;
let chunks = [];
let start = wholesPart.length % chunkSize;
if(start != 0) {
    chunks.push(wholesPart.slice(0, start));
}
for(let i = start; i < wholesPart.length; i+= chunkSize) {
    chunks.push(wholesPart.slice(i, i + chunkSize));
}
return chunks.join(thousandSep)

When I saw fstChunk the first thing I thought was 'fast chunk', but I guess it's supposed to be 'first chunk'. There is no reason make things less clear just to save 2 characters.

You don't need to check the length of wholesPart, placeThousands can handle short strings.

return placeThousands(wholesPart) + decimalPart;
2 of 2
1

Style and code

  • For max integer value use Number.MAX_SAFE_INTEGER

  • Use === rather than == and !== rather than !=

  • typeof is not a function. typeof(numToFormat) == 'number'; can be written typeof numToFormat === "number";

  • Use isNaN(number) to determine if a variable is "Not a Number"

  • Use Number(val) to convert to a number rather than parseFloat(val)

  • If you are going to exit on NaN or out of range do it early rather than after you process everything.

  • If a variable is not going to change define it as a constant with const

  • neat is a rather ambiguous name for the function. Maybe formatNumber would be better

  • Spaces between operators make the code more readable. nextLoop = i+3; as nextLoop = i + 3;

  • Space between if and ( also for ( , while ( and other tokens followed by (. And space between ) {

Logic

The whole thing feels over complicated. For values under 1000 all you do is maybe replace the decimal point. For other values you need only handle the thousands separator.

There is also the issues of negative numbers. You don't return a string saying No can do. The value you return will have a 1000 separator in the wrong place if the number length is divisible by 3 eg neat(-100) returns "-.100,00"

Rewrite

  • The rewrite fixes the negative number problem.

  • I added a places variable so that the number of decimal places can be set.

  • Uses default parameters to define defaults for (new places arg), thousandSep and decimalSep

  • Rather than return error string I return the number argument. It is likely that if the value overflows or is not a number the calling code will not check if the result is one of the error strings. This way what goes in will still have meaning when it comes out.

Code

function formatNumber(number, thousandSep = ",", decimalSep = ".", places = 2) {
    if (isNaN(number)) { return  number }
    var result = number < 0 ? "-" : "";
    number = Math.abs(number);
    if (number >= Number.MAX_SAFE_INTEGER) { return result + number.toFixed(places) }
    
    var place = Math.ceil(Math.log10(number));

    if (place < 3) { 
        return result + number.toFixed(places).replace(".", decimalSep);
    }

    while (place--) {
        result += number / 10 ** place % 10 | 0;
        if (place > 0 && place % 3 === 0) { result += thousandSep }
    }
    
    return result + decimalSep + number.toFixed(places).split(".")[1];
}
Find elsewhere
๐ŸŒ
Seanmcp
seanmcp.com โ€บ articles โ€บ be-careful-parsing-formatted-numbers-in-javascript
Be careful parsing formatted numbers in JavaScript โ€“ seanmcp.com
December 20, 2022 - "1,000-2,000".split("-").map((string) => parseFloat(string)); // [1, 2] "1,000-2,000".split("-").map((string) => Number(string)); // [NaN, NaN]
๐ŸŒ
HCL Software
help.hcl-software.com โ€บ dom_designer โ€บ 9.0.1 โ€บ reference โ€บ r_wpdr_runtime_i18n_parsefloat_r.html
parseFloat (I18n - JavaScript) - HCL Product Documentation
For example, if the given locale is French, the string '10 000,3' will be interpreted as 10000.3, because the decimal separator in France is a comma and the thousand-separator is a white space. If the Locale parameter is missing or null, the string is interpreted according to the XSP server ...
Top answer
1 of 3
24

According to the specification, a DecimalLiteral is defined as:

DecimalLiteral ::
    DecimalIntegerLiteral . DecimalDigitsopt ExponentPartopt 
    . DecimalDigits ExponentPartopt 
    DecimalIntegerLiteral ExponentPartopt

and for satisfying the parseFloat argument:

  1. Let inputString be ToString(string).
  2. Let trimmedString be a substring of inputString consisting of the leftmost character that is not a StrWhiteSpaceChar and all characters to the right of that character.(In other words, remove leading white space.)
  3. If neither trimmedString nor any prefix of trimmedString satisfies the syntax of a StrDecimalLiteral (see 9.3.1), return NaN.
  4. Let numberString be the longest prefix of trimmedString, which might be trimmedString itself, that satisfies the syntax of a StrDecimalLiteral.
  5. Return the Number value for the MV

So numberString becomes the longest prefix of trimmedString that satisfies the syntax of a StrDecimalLiteral, meaning the first parseable literal string number it finds in the input. Only the . can be used to specify a floating-point number. If you're accepting inputs from different locales, use a string replace:

function parseLocalNum(num) {
    return +(num.replace(",", "."));
}

The function uses the unary operator instead of parseFloat because it seems to me that you want to be strict about the input. parseFloat("1ABC") would be 1, whereas using the unary operator +"1ABC" returns NaN. This makes it MUCH easier to validate the input. Using parseFloat is just guessing that the input is in the correct format.

2 of 3
15

use:

theNumber.toLocaleString();

to get a properly formatted string with the right decimal and thousands separators

Top answer
1 of 15
246

The reference cited in the original answer below was wrong. There is a built in function for this, which is exactly what kaiser suggests below: toLocaleString

So you can do:

(1234567.89).toLocaleString('en')              // for numeric input
parseFloat("1234567.89").toLocaleString('en')  // for string input

The function implemented below works, too, but simply isn't necessary.

(I thought perhaps I'd get lucky and find out that it was necessary back in 2010, but no. According to this more reliable reference, toLocaleString has been part of the standard since ECMAScript 3rd Edition [1999], which I believe means it would have been supported as far back as IE 5.5.)


Original Answer

According to this reference there isn't a built in function for adding commas to a number. But that page includes an example of how to code it yourself:

function addCommas(nStr) {
    nStr += '';
    var x = nStr.split('.');
    var x1 = x[0];
    var x2 = x.length > 1 ? '.' + x[1] : '';
    var rgx = /(\d+)(\d{3})/;
    while (rgx.test(x1)) {
            x1 = x1.replace(rgx, '$1' + ',' + '$2');
    }
    return x1 + x2;
}

Edit: To go the other way (convert string with commas to number), you could do something like this:

parseFloat("1,234,567.89".replace(/,/g,''))
2 of 15
139

If is about localizing thousands separators, delimiters and decimal separators, go with the following:

// --> numObj.toLocaleString( [locales [, options] ] )
parseInt( number ).toLocaleString();

There are several options you can use (and even locales with fallbacks):

number = 123456.7089;

result  = parseInt( number ).toLocaleString() + "<br>";
result += number.toLocaleString( 'de-DE' ) + "<br>";
result += number.toLocaleString( 'ar-EG' ) + "<br>";
result += number.toLocaleString( 'ja-JP', { 
  style           : 'currency',
  currency        : 'JPY',
  currencyDisplay : 'symbol',
  useGrouping     : true
} ) + "<br>";
result += number.toLocaleString( [ 'jav', 'en' ], { 
  localeMatcher            : 'lookup',
  style                    : 'decimal',
  minimumIntegerDigits     : 2,
  minimumFractionDigits    : 2,
  maximumFractionDigits    : 3,
  minimumSignificantDigits : 2,
  maximumSignificantDigits : 3
} ) + "<br>";

var el = document.getElementById( 'result' );
el.innerHTML = result;
<div id="result"></div>

Details on the MDN info page.

Edit: Commentor @I like Serena adds the following:

To support browsers with a non-English locale where we still want English formatting, use value.toLocaleString('en'). Also works for floating point.

๐ŸŒ
PHP
php.net โ€บ manual โ€บ en โ€บ function.number-format.php
PHP: number_format - Manual
number_format( float $num, int $decimals = 0, ?string $decimal_separator = ".", ?string $thousands_separator = "," ): string
๐ŸŒ
sqlpey
sqlpey.com โ€บ javascript โ€บ how-to-format-numbers-in-javascript-with-thousand-separators
How to Format Numbers in JavaScript with Thousand Separators โ€ฆ
November 23, 2024 - const numberFromString = parseFloat("1,234,567.89".replace(/,/g, '')); console.log(numberFromString); // Outputs: 1234567.89
๐ŸŒ
Stack Overflow
stackoverflow.com โ€บ questions โ€บ 59254397 โ€บ typescript-javascript-parse-float-with-comma-as-decimal-separator
Typescript/Javascript - Parse float with comma as decimal separator - Stack Overflow
December 10, 2019 - I will edit the post, In my system I have a function helper to convert the . as thousand separator and the comma as decimals separator and I cannot avoid that conversion ... Here is a clunky way of doing it. Using an array and reduce ยท const tests = ['70,65', '7,000,01', '700']; const parseNumber = (num) => { if(num === undefined) return undefined; if(num.indexOf(',') < 0) return parseFloat(num); const numArr = num.split(','); return parseFloat( numArr.reduce((a, v, i) => a + ((i === numArr.length - 1) ?