I find toLocaleString function very odd.
the following line will return 0.003:
alert(0.0031.toLocaleString(2))
this line will return 0:
alert(0.00031.toLocaleString(2))
why?
This is not a valid parameters to the method toLocaleString.
You can use minimumFractionDigits param like this:
var res = 0.00031.toLocaleString(undefined, {minimumFractionDigits: 4});
console.log(res);
The toLocaleString() method returns a string with a language sensitive representation of this number.
numObj.toLocaleString([locales [, options]]) has two parameters.
Reference https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toLocaleString
var num = 0.00031;
console.log(num.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2}));
console.log(num.toLocaleString(undefined, { maximumFractionDigits: 4}));
toLocaleString truncates and rounds the decimal number to 3 digits after the decimal.
0.0005.toLocaleString()
for example will return 0.001.
The 2 in that you pass in as a method param doesn't do anything.
2 is not a valid argument for toLocaleString method of a Number. You may only pass a locale, which is a string, and and an object of options.
Options object can be used, among other things, to specify number of fraction digits:
number.toLocaleString(undefined, { maximumFractionDigits: 4 })
And the default value for it happens to be 3:
maximumFractionDigits
The maximum number of fraction digits to use.
Possible values are from 0 to 20; the default for plain number
formatting is the larger of minimumFractionDigits and 3; the default
for currency formatting is the larger of minimumFractionDigits and the
number of minor unit digits provided by the ISO 4217 currency code
list (2 if the list doesn't provide that information); the default for
percent formatting is the larger of minimumFractionDigits and 0.
The number 2 in the argument is not making any difference. toLocaleString returns a string with a language sensitive representation of the number.
In the second case of your problem it is basically 0.000 which is equal to 0
console.log("Passing argument " + 0.0031.toLocaleString(2))
console.log("Without argument " + 0.0031.toLocaleString())
console.log("Zeros " + 0.000)
number.toLocaleString() returns language sensitive representation of the number. Here in your case you are first not passing any locale information, and you are not telling this function that what is your max fraction limit.
See this example
0.0003.toLocaleString(undefined, {minimumFractionDigits: 2})
"0.00"
0.0003.toLocaleString(undefined, {minimumFractionDigits: 3})
"0.000"
0.0003.toLocaleString(undefined, {minimumFractionDigits: 4})
"0.0003
As per spec, first two arguments to toLocaleString is locale and options
When the toLocaleString method is called with optional arguments
locales and options, the following steps are taken:
When this API receive value 2 or 3, it first try to resolve locales and if not found the check within the supported locales.
The resolved locale is used as an effective locale to format the number as per the locale as per Common Locale Data Repository.
NOTE It is recommended that implementations use the locale data
provided by the Common Locale Data Repository (available at
http://cldr.unicode.org/).
As per documentation
The locales argument must be either a string holding a BCP 47 language
tag, or an array of such language tags. If the locales argument is not
provided or is undefined, the runtime's default locale is used.
A BCP 47 language tag defines a language and minimally contains a
primary language code. In its most common form it can contain, in
order: a language code, a script code, and a country or region code,
all separated by hyphens. While the tag is not case sensitive, it is
recommended to use title case for script code, upper case for country
and region codes and lower case for everything else.
Finally, lookup is performed to find the best fit from the supported locales as per BCP47 logic as per locales registered in IANA language subtag registry as per various attributes of a language mentioned.
2 doesn't matches any of the supported locales so, default maximum fraction digits as per your system environment is used from available value (appears to be 3 in your case.)
Hence you get
0.00031.toLocaleString(2) //"0"
0.0031.toLocaleString(2) //"0.003"
Related
I have a scenario where I need to parsefloat 19 digit string to number.
e.g. parseFloat("1000000000100000043") gives me 1000000000100000000
but the expected output required is 1000000000100000043
This is likely a precision overflow error.
The Number data type (but also int and float in other languages) have a finite number of bits available to represent a number. Typically around 15-16 decimal digits worth.
When length of original number in the string exceeds available precision, such number can no longer be represented by the target data type.
In this case the parseFloat function fails silently. If you want to catch this situation you need to add code to check incoming data or use another function, possibly a custom one.
Alternatively, you can convert the numeric value back to string and compare it with original to detect a discrepancy.
See also a question regarding double.Parse
You are running into how Javascript numbers are stored. See, e.g., here: https://www.w3schools.com/js/js_numbers.asp
You can use a library like decimal.js to work with large, exact numbers. These libraries store the number as string, but allow you to do mathematical operations.
My angular program, I need to pass the number which is more than 20 digit to the API request.
num: any;
this.num = 2019111122001424290521878689;
console.log(this.num); // It displays "2.0191111220014244e+27"
I tried to change string from number as below
console.log(this.num.toString()); // It displays "2.0191111220014244e+27"
My expectation is that I need to pass the original big integer into the API request. If I pass as below, it goes as "2.0191111220014244e+27".
BTW, I tried BigInt(this.num), which gives difference number.
Suggest me
In JavaScript, big integer literals have the letter n as a suffix:
var bigNum = 2019111122001424290521878689n;
console.log(bigNum);
For more information, see
MDN JavaScript Reference - BigInt
If you got a large number (> SAFE_INTEGER) from an API, in JSON format, and you want to get the exact value, as as string, you unfortunately can't use JSON.parse(), as it will use the number type and lose precision.
There are alternative JSON parsers out there like LosslessJSON that might solve your problem.
You can use BigInt.
BigInt is a built-in object that provides a way to represent whole numbers larger than 253 - 1, which is the largest number JavaScript can reliably represent with the Number primitive. BigInt can be used for arbitrarily large integers.
const theBiggestInt = 9007199254740991n;
const alsoHuge = BigInt(9007199254740991);
// ↪ 9007199254740991n
const hugeString = BigInt("9007199254740991");
// ↪ 9007199254740991n
const hugeHex = BigInt("0x1fffffffffffff");
// ↪ 9007199254740991n
const hugeBin = BigInt("0b11111111111111111111111111111111111111111111111111111");
// ↪ 9007199254740991n
BigInt is similar to Number in some ways, but also differs in a few key matters — it cannot be used with methods in the built-in Math object and cannot be mixed with instances of Number in operations; they must be coerced to the same type. Be careful coercing values back and forth, however, as the precision of a BigInt may be lost when it is coerced to a Number.
Refer to
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt
The problem is that the number you have there is not an integer. Javascript can only store integers up to the value given by Number.MAX_SAFE_INTEGER. In chrome, this number is 9007199254740991.
The number you have is actually a floating point number, and converting it between floating point and integer will loose some precision.
Is there something i can do here
const ecommerce = {
purchase: {
actionField: {
},
},
}
As it looks like, the inputted value is a string. You could convert the string to number by using an unary plus + in front of the variable.
name: "PRICEPLAN-" + +price,
An other way would include some sanity checks and urges the user to input a valid value.
#Nina Scholz' answer is correct and concise. The other way in JavaScript to do this, and which I personally prefer because it's more semantic, is to use Number().
name: "PRICEPLAN-" + Number(price),
I find that good semantics make it easier for others to understand my code (and for me too, when I come back to it 6 months later.)
As others have pointed out, this will not coerce your values to an integer, so you will want to be sure about your inputs.
If you want Integer value, then you can use var parseInt() function in JS
var a = parseInt("10.00")
will convert it to "10"
radix :
An integer between 2 and 36 that represents the radix (the base in mathematical numeral systems) of the above mentioned string. Specify 10 for the decimal numeral system commonly used by humans. Always specify this parameter to eliminate reader confusion and to guarantee predictable behavior.
After adding radix it will assure the output will be decimal :
var a = parseInt("010.00", 10)
To be sure to have an Interger, use parseInt(). As Number() won't prevent numbers like 3.11 to be transformed to Integers.
name: "PRICEPLAN-" + parseInt(price),
And using ES6 template notation:
name: `PRICEPLAN-${parseInt(price)}`,
I format a float to a locale string (Euro) and there are very different results in every browser. Is it possible to fix without an own function?
var sum=2282.0000;
var formated_sum = Number(sum.toFixed(2)).toLocaleString("de-DE", {style: "currency", currency: "EUR"});
Firefox result: 2.282,00 €
Chrome result: 2.282 €
IE result: 2.282,00 €
Safari result: 2282 €
Safari results are very much wrong, chrome results are not so much bad.
Any Idea how to fix that without writing an own function for formatting?
This question may already have an answer here:
Inconsistent behavior of toLocaleString() in different browser
No, my question is different because i am searching for a solution for Currency, not DATE
ECMA 262 specifies that the function is implementation dependent and takes no arguments.
Produces a String value that represents this Number value formatted
according to the conventions of the host environment’s current locale.
This function is implementation-dependent, and it is permissible, but
not encouraged, for it to return the same thing as toString.
NOTE The first parameter to this function is likely to be used in a
future version of this standard; it is recommended that
implementations do not use this parameter position for anything else.
It is also in ECMA internationalization API specification (which for Number.prototype.toLocaleString supersedes ECMA 262 but accepts 2 arguments)
This definition supersedes the definition provided in ES5, 15.7.4.3.
When the toLocaleString method is called with optional arguments
locales and options, the following steps are taken:
Let x be this Number value (as defined in ES5, 15.7.4). If locales is
not provided, then let locales be undefined. If options is not
provided, then let options be undefined. Let numberFormat be the
result of creating a new object as if by the expression new
Intl.NumberFormat(locales, options) where Intl.NumberFormat is the
standard built-in constructor defined in 11.1.3. Return the result of
calling the FormatNumber abstract operation (defined in 11.3.2) with
arguments numberFormat and x. The value of the length property of the
toLocaleString method is 0.
Besides, mdn specifies that Safari has no support for it.
As for a viable solution see this answer on SO
I have a question about the default behavior of JavaScript's parseFloat function in different parts of the world.
In the US, if you call parseFloat on a string "123.34", you'd get a floating point number 123.34.
If I'm developing code in say Sweden or Brazil and they use a comma instead of a period as the decimal separator, does the parseFloat function expect "123,34" or "123.34".
Please note that I'm not asking how to parse a different culture's number format in the US. I'm asking does parseFloat in Sweden or Brazil behave the same way it does inside the US, or does it expect a number in its local format? Or to better think about this, does a developer in Brazil/Sweden have to convert strings to English format before it can use parseFloat after extracting text from a text box?
Please let me know if this doesn't make sense.
parseFloat doesn't use your locale's definition, but the definition of a decimal literal.
It only parses . not ,
I'm brazilian and I have to replace comma with dot before parsing decimal numbers.
parseFloat specification
No, parseFloat is specified to parse DecimalLiterals, which use the dot as decimal separator. It does not depend on the current environment's locale settings.
It’s not just Sweden/Brazil. F.ex in US they often add commas in large numbers, like $5,762,325.25.
The parseFloat function essentially deals with decimals, not locale strings.
In general, JavaScript can sometimes convert generic strings/numbers/dates to locale-friendly formats, but not the other way around.
Complementing the answer given by FrancescoMM, you must use regex for really big numbers. String.replace using string as a parameter will replace only the first occurrence. So 999.999.999,99 becomes 999999.999.99
stringNum.replace(/\./g, "").replace(/\,/g, ".")
Source:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/replace
If you are sure it is in Brasilian format, just convert the number to US format before parsing.
function parseItalianNumber(stringNum) {
return parseFloat(stringNum.replaceAll(".","").replaceAll(",","."));
}
in Italy we also use . as a thousands separator. This removes any thousands separators, just in case (you do not want many dots around), and then converts the comma to a dot, before calling parseFloat.