While working with locale translation and parsing decimal numbers from text to numerical values in Angular 10, I came across the following problem:
Consider the string value value = "-35.17 %". I want to convert this a numerical value using parseFloat(value). This works fine for application locale en-US.
However, if the user changes application locale to nb-NO (Norwegian), the parsing fails, resulting in a NaN.
The reason for this is that the Norwegian locale uses a different character for the negative prefix (− instead of -).
The workaround for this particular issue is simple, by performing a .replace("−", "-") on the string before parsing, but shouldn't JavaScript be able to handle parsing of both these characters? Is it only safe to perform parsing on locale en-US?
The JavaScript function parseFloat() needs an input string that meets certain requirements, including (but not limited to) the following:
If parseFloat encounters a character other than a plus sign (+), minus sign (- U+002D HYPHEN-MINUS), numeral (0–9), decimal point (.), or exponent (e or E), it returns the value up to that character, ignoring the invalid character and characters following it.
Localized strings may contain characters that does not meet those requirements.
Related
Is it possible to keep trailing or leading zeroes on a number in javascript, without using e.g. a string instead?
const leading = 003; // literal, leading
const trailing = 0.10; // literal, trailing
const parsed = parseFloat('0.100'); // parsed or somehow converted
console.log(leading, trailing, parsed); // desired: 003 0.10 0.100
This question has been regularly asked (and still is), yet I don't have a place I'd feel comfortable linking to (did i miss it?).
Fully analogously would be keeping any other aspect of the representation a number literal was entered as, although asked nowhere near as often:
console.log(0x10); // 16 instead of potentially desired 0x10
console.log(1e1); // 10 instead of potentially desired 1e1
For disambiguation, this is not about the following topics, for some of which I'll add links, as they might be of interest as well:
Padding to a set amount of digits, formatting to some specific string representation, e.g. How can i pad a value with leading zeroes?, How to output numbers with leading zeros in JavaScript?, How to add a trailing zero to a price
Why a certain string representation will be produced for some number by default, e.g. How does JavaScript determine the number of digits to produce when formatting floating-point values?
Floating point precision/accuracy problems, e.g. console.log(0.1 + 0.2) producing 0.30000000000000004, see Is floating point math broken?, and How to deal with floating point number precision in JavaScript?
No. A number stores no information about the representation it was entered as, or parsed from. It only relates to its mathematical value. Perhaps reconsider using a string after all.
If i had to guess, it would be that much of the confusion comes from the thought, that numbers, and their textual representations would either be the same thing, or at least tightly coupled, with some kind of bidirectional binding between them. This is not the case.
The representations like 0.1 and 0.10, which you enter in code, are only used to generate a number. They are convenient names, for what you intend to produce, not the resulting value. In this case, they are names for the same number. It has a lot of other aliases, like 0.100, 1e-1, or 10e-2. In the actual value, there is no contained information, about what or where it came from. The conversion is a one-way street.
When displaying a number as text, by default (Number.prototype.toString), javascript uses an algorithm to construct one of the possible representations from a number. This can only use what's available, the number value, also meaning it will produce the same results for two same numbers. This implies, that 0.1 and 0.10 will produce the same result.
Concerning the number1 value, javascript uses IEEE754-2019 float642. When source code is being evaluated3, and a number literal is encountered, the engine will convert the mathematical value the literal represents to a 64bit value, according to IEEE754-2019. This means any information about the original representation in code is lost4.
There is another problem, which is somewhat unrelated to the main topic. Javascript used to have an octal notation, with a prefix of "0". This means, that 003 is being parsed as an octal, and would throw in strict-mode. Similarly, 010 === 8 (or an error in strict-mode), see Why JavaScript treats a number as octal if it has a leading zero
In conclusion, when trying to keep information about some representation for a number (including leading or trailing zeroes, whether it was written as decimal, hexadecimal, and so on), a number is not a good choice. For how to achieve some specific representation other than the default, which doesn't need access to the originally entered text (e.g. pad to some amount of digits), there are many other questions/articles, some of which were already linked.
[1]: Javascript also has BigInt, but while it uses a different format, the reasoning is completely analogous.
[2]: This is a simplification. Engines are allowed to use other formats internally (and do, e.g. to save space/time), as long as they are guaranteed to behave like an IEEE754-2019 float64 in any regard, when observed from javascript.
[3]: E.g. V8 would convert to bytecode earlier than evaluation, already exchanging the literal. The only relevant thing is, that the information is lost, before we could do anything with it.
[4]: Javascript gives the ability to operate on code itself (e.g. Function.prototype.toString), which i will not discuss here much. Parsing the code yourself, and storing the representation, is an option, but has nothing to do with how number works (you would be operating on code, a string). Also, i don't immediately see any sane reason to do so, over alternatives.
I have different numbers from 100.000 to 3.000.000 saved as a String. I Want to convert them into a number in exact the same format with the parsefloat function and sum them after it. With numbers under 1 million and only one dot it will working, with a number over one million it deletes the last numbers after the dot. for example when the productionItem.calculationResult.stromKwh = 1.358.149 the result it 1.358.
result is 1358.149 parseFloat(String(productionItem.calculationResult.stromKwh).replace('.','').replace(',','.'));
result is 1.358
parseFloat(String(productionItem.calculationResult.stromKwh).replace(',','.'));
First of all you need to understand that different locales use different number formatting characters. In english locales, decimals are separated using a dot (3.14159265) and thousands are separated using commas (1,000,000 is a million).
In german locales, these are reversed. Your numbers are formatted according to german locale rules.
Programming languages almost always use english locale conventions but without thousands separators. The dot is interpreted as the decimal point. parsefloat() parses numbers as JavaScript would do it, using the dot as the decimals separator.
Sadly, JavaScript has locale-specific number formatting (toLocaleString()) but no corresponding parsing functions. There are libraries which provide these, have a look at How do I convert String to Number according to locale (opposite of .toLocaleString)? for a discussion.
I have been trying the following code to get the ASCII equivalent character
String.fromCharCode("149")
but, it seems to work till 126 is passed as parameter. But for 149, the symbol generated should be
•
128 and beyond is not standard ASCII.
var s = "•";
alert(s.charCodeAt(0))
gives 8226
https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/String/fromCharCode
Getting it to work with higher values Although most common Unicode
values can be represented with one 16-bit number (as expected early on
during JavaScript standardization) and fromCharCode() can be used to
return a single character for the most common values (i.e., UCS-2
values which are the subset of UTF-16 with the most common
characters), in order to deal with ALL legal Unicode values (up to 21
bits), fromCharCode() alone is inadequate. Since the higher code point
characters use two (lower value) "surrogate" numbers to form a single
character, String.fromCodePoint() (part of the ES6 draft) can be used
to return such a pair and thus adequately represent these higher
valued characters.
The fromCharCode() method converts Unicode values into characters.
to use unicode see the link for unicode table
http://unicode-table.com/en/
I got String.fromCodePoint(149) to show inside an alert in firefox but not in IE & Chrome. It may be because of browser language settings.
But this looks correct accourding to the ASCII table.
http://www.asciitable.com/
This is the code I used
alert(String.fromCodePoint(149));
I am attempting to develop a conversion website that takes a numeric value:
1,200.12
or
1.200,12
or
1200.12
or
1200,12
and have them all interpreted as 1200.12 by parseFloat.
I would also like decimals to be able to be interpreted.
0.123
or
0,123
as 0.123
through a textarea and then parseFloat the number in order to perform calculations.
These are the results I am getting:
textarea input = 12,000.12
value after parseFloat = 12
Does parseFloat not recognize the formatting of the numbers?
i get the same results with:
textarea input: 12.000,12
value after parseFloat = 12
How do I solve this problem? It would seem I need to strip out the commas since parseFloat doesn't read beyond them and with european notation strip the decimals and change the comma to a decimal for parseFloat to read the input correctly. Any ideas on how to solve this? My guess is I would need to identify the string input as either european or american decimal notation and then perform the required actions to prepare the string for parseFloat. How would I go about achieving that? All contributions are appreciated. Using HTML5 and Javascript. This is my first website so please go easy on me.
Best,
RP
To all contributors...Thank you! So far all the input has been sweet. I don't think we are going to be able to use a single replace statement to correctly strip both european and american notation so I think I should use REGEX somehow to determine the notation and then split into an if else statement to perform separate replace functions on each individual notation.
var input, trim;
input = "1.234,56" //string from textarea on page
if(/REGEX that determines American Notation/.test(input){
trim = input.replace(/\,/,"");//removes commas and leaves decimal point);
}
else(/REGEX that determine European Notation/.test(input)/){ //would qualify input here
rep = input.replace(/\./,"");//removes all decimal points);
trim = rep.replace(/\,/,"."//changes the remaining comma to a decimal);
}
//now either notation should be in the appropriate form to parse
number = parseFloat(trim);
Is this possible using REGEX? Please see my other question.
Regex - creating an input/textarea that correctly interprets numbers
One way would be to strip the comma signs, for example with:
.replace(",", "")
From there you should be able to parseFloat
Updated with fiddle: http://jsfiddle.net/aLv74xpu/2/
Here is a solution that uses a regular expression to eliminate all commas and all periods, except the last one.
var number = "1,234.567.890";
var replaced = number.replace(/,|\.(?=.*\.)/g, "");
var result = parseFloat(replaced);
// result === 1234567.89
Alternatively, you can use this, which treats commas and periods identically, and ignores them all except for the last one.
var number = "12.345,67";
var replaced = number.replace(/[.,](?=.*[.,])/g, "").replace(",", ".");
var result = parseFloat(replaced);
// result === 12345.67
parseFloat parses its argument, a string, and returns a floating point
number. If it encounters a character other than a sign (+ or -),
numeral (0-9), a decimal point, or an exponent, it returns the value
up to that point and ignores that character and all succeeding
characters. Leading and trailing spaces are allowed.
From the good MDN network: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseFloat
So it is the expected behaviour of parseFloat
My problem is really simple but I'm not sure if there's a "native" solution using JSON.parse.
I receive this string from an API :
{ "key" : -922271061845347495 }
When I'm using JSON.parse on this string, it turns into this object:
{ "key" : -922271061845347500 }
As you can see, the parsing stops when the number is too long (you can check this behavior here). It has only 15 exact digits, the last one is rounded and those after are set to 0. Is there a "native" solution to keep the exact value ? (it's an ID so I can't round it)
I know I can use regex to solve this problem but I'd prefer to use a "native" method if it exists.
Your assumption that the parsing stops after certain digits is incorrect.
It says here:
In JavaScript all numbers are floating-point numbers. JavaScript uses
the standard 8 byte IEEE floating-point numeric format, which means
the range is from:
±1.7976931348623157 x 10308 - very large, and ±5 x 10-324 - very small.
As JavaScript uses floating-point numbers the accuracy is only assured
for integers between: -9007199254740992 (-253) and 9007199254740992
(253)
You number lies outside the "accurate" range hence it is converted to the nearest representation of the JavaScript number. Any attempt to evaluate this number (using JSON.parse, eval, parseInt) will cause data loss. I therefore recommend that you pass the key as a string. If you do not control the API, file a feature request.
The number is too big to be parsed correctly.
One solution is:
Preprocessing your string from API to convert it into string before parsing.
Preform normal parsing
Optionally, you could convert it back into number for your own purpose.
Here is the RegExp to convert all numbers in your string (proceeded with :) into strings:
// convert all number fields into strings to maintain precision
// : 922271061845347495, => : "922271061845347495",
stringFromApi = stringFromApi.replace(/:\s*(-?\d+),/g, ': "$1",');
Regex explanation:
\s* any number of spaces
-? one or zero '-' symbols (negative number support)
\d+ one or more digits
(...) will be put in the $1 variable