Convert String with Dot or Comma as decimal separator to number in JavaScript

JavascriptJqueryString ParsingData Conversion

Javascript Problem Overview


An input element contains numbers a where comma or dot is used as decimal separator and space may be used to group thousands like this:

> '1,2'
> '110 000,23'
> '100 1.23'

How would one convert them to a float number in the browser using JavaScript?

jQuery and jQuery UI are used. Number(string) returns NaN and parseFloat() stops on first space or comma.

Javascript Solutions


Solution 1 - Javascript

Do a replace first:

parseFloat(str.replace(',','.').replace(' ',''))

Solution 2 - Javascript

I realise I'm late to the party, but I wanted a solution for this that properly handled digit grouping as well as different decimal separators for currencies. As none of these fully covered my use case I wrote my own solution which may be useful to others:

function parsePotentiallyGroupedFloat(stringValue) {
    stringValue = stringValue.trim();
    var result = stringValue.replace(/[^0-9]/g, '');
    if (/[,\.]\d{2}$/.test(stringValue)) {
        result = result.replace(/(\d{2})$/, '.$1');
    }
    return parseFloat(result);
}

This should strip out any non-digits and then check whether there was a decimal point (or comma) followed by two digits and insert the decimal point if needed.

It's worth noting that I aimed this specifically for currency and as such it assumes either no decimal places or exactly two. It's pretty hard to be sure about whether the first potential decimal point encountered is a decimal point or a digit grouping character (e.g., 1.542 could be 1542) unless you know the specifics of the current locale, but it should be easy enough to tailor this to your specific use case by changing \d{2}$ to something that will appropriately match what you expect to be after the decimal point.

Solution 3 - Javascript

The perfect solution

accounting.js is a tiny JavaScript library for number, money and currency formatting.

Check this for ref

Solution 4 - Javascript

You could replace all spaces by an empty string, all comas by dots and then parse it.

var str = "110 000,23";
var num = parseFloat(str.replace(/\s/g, "").replace(",", "."));
console.log(num);

I used a regex in the first one to be able to match all spaces, not just the first one.

Solution 5 - Javascript

This is the best solution

http://numeraljs.com/

numeral().unformat('0.02'); = 0.02

Solution 6 - Javascript

What about:

parseFloat(str.replace(' ', '').replace('.', '').replace(',', '.'));

Solution 7 - Javascript

All the other solutions require you to know the format in advance. I needed to detect(!) the format in every case and this is what I end up with.

function detectFloat(source) {
	let float = accounting.unformat(source);
	let posComma = source.indexOf(',');
	if (posComma > -1) {
		let posDot = source.indexOf('.');
		if (posDot > -1 && posComma > posDot) {
			let germanFloat = accounting.unformat(source, ',');
			if (Math.abs(germanFloat) > Math.abs(float)) {
				float = germanFloat;
			}
		} else {
			// source = source.replace(/,/g, '.');
			float = accounting.unformat(source, ',');
		}
	}
	return float;
}

This was tested with the following cases:

		const cases = {
			"0": 0,
			"10.12": 10.12,
			"222.20": 222.20,
			"-222.20": -222.20,
			"+222,20": 222.20,
			"-222,20": -222.20,
			"-2.222,20": -2222.20,
			"-11.111,20": -11111.20,
		};

Suggestions welcome.

Solution 8 - Javascript

Here's a self-sufficient JS function that solves this (and other) problems for most European/US locales (primarily between US/German/Swedish number chunking and formatting ... as in the OP). I think it's an improvement on (and inspired by) Slawa's solution, and has no dependencies.

function realParseFloat(s)
{
    s = s.replace(/[^\d,.-]/g, ''); // strip everything except numbers, dots, commas and negative sign
    if (navigator.language.substring(0, 2) !== "de" && /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(s)) // if not in German locale and matches #,###.######
    {
        s = s.replace(/,/g, ''); // strip out commas
        return parseFloat(s); // convert to number
    }
    else if (/^-?(?:\d+|\d{1,3}(?:\.\d{3})+)(?:,\d+)?$/.test(s)) // either in German locale or not match #,###.###### and now matches #.###,########
    {
        s = s.replace(/\./g, ''); // strip out dots
        s = s.replace(/,/g, '.'); // replace comma with dot
        return parseFloat(s);
    }
    else // try #,###.###### anyway
    {
        s = s.replace(/,/g, ''); // strip out commas
        return parseFloat(s); // convert to number
    }
}

Solution 9 - Javascript

Here is my solution that doesn't have any dependencies:

return value
  .replace(/[^\d\-.,]/g, "")   // Basic sanitization. Allows '-' for negative numbers
  .replace(/,/g, ".")          // Change all commas to periods
  .replace(/\.(?=.*\.)/g, ""); // Remove all periods except the last one

(I left out the conversion to a number - that's probably just a parseFloat call if you don't care about JavaScript's precision problems with floats.)

The code assumes that:

  • Only commas and periods are used as decimal separators. (I'm not sure if locales exist that use other ones.)
  • The decimal part of the string does not use any separators.

Solution 10 - Javascript

This answer accepts some edge cases that others don't:

  • Only thousand separator: 1.000.000 => 1000000
  • Exponentials: 1.000e3 => 1000e3 (1 million)

Run the code snippet to see all the test suite.

const REGEX_UNWANTED_CHARACTERS = /[^\d\-.,]/g
const REGEX_DASHES_EXEPT_BEGINNING = /(?!^)-/g
const REGEX_PERIODS_EXEPT_LAST = /\.(?=.*\.)/g

export function formatNumber(number) {
  // Handle exponentials
  if ((number.match(/e/g) ?? []).length === 1) {
    const numberParts = number.split('e')
    return `${formatNumber(numberParts[0])}e${formatNumber(numberParts[1])}`
  }

  const sanitizedNumber = number
    .replace(REGEX_UNWANTED_CHARACTERS, '')
    .replace(REGEX_DASHES_EXEPT_BEGINING, '')

  // Handle only thousands separator
  if (
    ((sanitizedNumber.match(/,/g) ?? []).length >= 2 && !sanitizedNumber.includes('.')) ||
    ((sanitizedNumber.match(/\./g) ?? []).length >= 2 && !sanitizedNumber.includes(','))
  ) {
    return sanitizedNumber.replace(/[.,]/g, '')
  }

  return sanitizedNumber.replace(/,/g, '.').replace(REGEX_PERIODS_EXEPT_LAST, '')
}

function formatNumberToNumber(number) {
  return Number(formatNumber(number))
}

const REGEX_UNWANTED_CHARACTERS = /[^\d\-.,]/g
const REGEX_DASHES_EXEPT_BEGINING = /(?!^)-/g
const REGEX_PERIODS_EXEPT_LAST = /\.(?=.*\.)/g

function formatNumber(number) {
  if ((number.match(/e/g) ?? []).length === 1) {
    const numberParts = number.split('e')
    return `${formatNumber(numberParts[0])}e${formatNumber(numberParts[1])}`
  }

  const sanitizedNumber = number
    .replace(REGEX_UNWANTED_CHARACTERS, '')
    .replace(REGEX_DASHES_EXEPT_BEGINING, '')

  if (
    ((sanitizedNumber.match(/,/g) ?? []).length >= 2 && !sanitizedNumber.includes('.')) ||
    ((sanitizedNumber.match(/\./g) ?? []).length >= 2 && !sanitizedNumber.includes(','))
  ) {
    return sanitizedNumber.replace(/[.,]/g, '')
  }

  return sanitizedNumber.replace(/,/g, '.').replace(REGEX_PERIODS_EXEPT_LAST, '')
}

const testCases = [
  '1',
  '1.',
  '1,',
  '1.5',
  '1,5',
  '1,000.5',
  '1.000,5',
  '1,000,000.5',
  '1.000.000,5',
  '1,000,000',
  '1.000.000',

  '-1',
  '-1.',
  '-1,',
  '-1.5',
  '-1,5',
  '-1,000.5',
  '-1.000,5',
  '-1,000,000.5',
  '-1.000.000,5',
  '-1,000,000',
  '-1.000.000',

  '1e3',
  '1e-3',
  '1e',
  '-1e',
  '1.000e3',
  '1,000e-3',
  '1.000,5e3',
  '1,000.5e-3',
  '1.000,5e1.000,5',
  '1,000.5e-1,000.5',

  '',
  'a',
  'a1',
  'a-1',
  '1a',
  '-1a',
  '1a1',
  '1a-1',
  '1-',
  '-',
  '1-1'
]

document.getElementById('tbody').innerHTML = testCases.reduce((total, input) => {
  return `${total}<tr><td>${input}</td><td>${formatNumber(input)}</td></tr>`
}, '')

<table>
  <thead><tr><th>Input</th><th>Output</th></tr></thead>
  <tbody id="tbody"></tbody>
</table>

Solution 11 - Javascript

try this...

var withComma = "23,3";
var withFloat = "23.3";

var compareValue = function(str){
  var fixed = parseFloat(str.replace(',','.'))
  if(fixed > 0){
      console.log(true)
    }else{
      console.log(false);
  }
}
compareValue(withComma);
compareValue(withFloat);

Solution 12 - Javascript

From number to currency string is easy through Number.prototype.toLocaleString. However the reverse seems to be a common problem. The thousands separator and decimal point may not be obtained in the JS standard.

In this particular question the thousands separator is a white space " " but in many cases it can be a period "." and decimal point can be a comma ",". Such as in 1 000 000,00 or 1.000.000,00. Then this is how i convert it into a proper floating point number.

var price = "1 000.000,99",
    value = +price.replace(/(\.|\s)|(\,)/g,(m,p1,p2) => p1 ? "" : ".");
console.log(value);

So the replacer callback takes "1.000.000,00" and converts it into "1000000.00". After that + in the front of the resulting string coerces it into a number.

This function is actually quite handy. For instance if you replace the p1 = "" part with p1 = "," in the callback function, an input of 1.000.000,00 would result 1,000,000.00

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAndrusView Question on Stackoverflow
Solution 1 - JavascripthytestView Answer on Stackoverflow
Solution 2 - JavascriptThor84noView Answer on Stackoverflow
Solution 3 - JavascriptShafiqView Answer on Stackoverflow
Solution 4 - JavascriptAlex TurpinView Answer on Stackoverflow
Solution 5 - JavascriptstuartchaneyView Answer on Stackoverflow
Solution 6 - Javascriptlpinto.euView Answer on Stackoverflow
Solution 7 - JavascriptSlawaView Answer on Stackoverflow
Solution 8 - JavascriptniceblueView Answer on Stackoverflow
Solution 9 - JavascriptbcodyView Answer on Stackoverflow
Solution 10 - JavascriptMaurici AbadView Answer on Stackoverflow
Solution 11 - JavascriptjosgallView Answer on Stackoverflow
Solution 12 - JavascriptReduView Answer on Stackoverflow