What does character 'n' after numeric literal mean in JavaScript? - javascript

I've seen
const num = 123456789000000000000n;
And don't know what the n at the end of numeric literal does?
At the time of writing, when searching online for "What does character 'n' after numeric literal mean in JavaScript" nothing comes up.

From BigInt on MDN:
A BigInt is created by appending n to the end of an integer literal —
10n — or by calling the function BigInt().
In essence, BigInt allows for storing large integers, as otherwise a large numeric literal would be converted into a floating point and lose precision of the least significant digits.

Related

how to handle more than 20 digit number (Big integer)?

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 `10e1` an Integer literal or Floating point literal?

I was looking into this article and wondering if 10e1 is an Integer Literal or a Floating Point Literal.
I know that 100 is an Integer literal. Does it make any difference if I write 10e1 instead?
When I check in the spec here(7) or here(5.1), there is nothing called "Floating Point Literal". Is this just another incorrect doc in MDN? Any idea what Floating Point Literal refers to?
To summarise:
Does 100 and 10e1 fall into same category of literals? If yes, which?
Is there something called "Floating Point Literal"?
Does it make any difference if I write 10e1 instead of 100?
Not for the result, no. But it's one character more to transfer and parse (so better use 1e2 :-D), and it will affect readability. Not everyone is familiar with exponents.
In the spec there is nothing called "Floating Point Literal". Is this just another incorrect doc in MDN?
The MDN guide is dubious for sure, naming a sections "Integers" in an article about JS types is confusing at least.
Does 100 and 10e1 fall into same category of literals? If yes, which?
Yes, they're both numeric literals. JS does not distinguish between numbers with and without a fractional part, they all have the same floating-point type. There is only one grammar for decimal number literals, with fractional digits and exponents being optional.
Any idea what Floating Point Literal refers to?
It's meant as "(number) literal for a floating-point number", just as "Integer literal" means "(number) literal for a floating-point number representing an integer".
DecimalLiteral::
DecimalIntegerLiteral.DecimalDigits(opt) ExponentPart(opt)
.DecimalDigits ExponentPart(opt)
DecimalIntegerLiteral ExponentPart(opt)
DecimalIntegerLiteral::
0
NonZeroDigitDecimalDigitsopt
As per spec, 100 and 10e1 are both "DecimalLiteral" while 100 also qualifies to be "DecimalIntegerLiteral"
None of these should make any real difference to the developer as mentioned in comments by #Thilo
The internal representation as per IEEE-754 should as well be the same.
Status Sign [1] Exponent [11] Significand [52]
Normal 0 (+) 10000000101 (+6) 1.1001000000000000000000000000000000000000000000000000 (1.5625)

facing an issue with parseFloat when input is more than 16 digits

I am facing weird issued.
parseFloat(11111111111111111) converts it to 11111111111111112.
I noticed that it works fine till length is 16 but rounds off higher when input length is > 16.
I want to retain the original value passed in parseFloat after it is executed.
Any help?
Integers (numbers without a period or exponent notation) are considered accurate up to 15 digits.
More information here
Numbers in javascript are represented using 64 bit floating point values (so called doubles in other languages).
doubles can hold at most 15/16 significant digits (depends on number magnitute). Since range of double is 1.7E+/-308 some numbers can only be aproximated by double, in your case 11111111111111111 cannot be represented exactly but is aproximated by 11111111111111112 value. If this sounds strange then remember that 0.3 cannot be represented exactly as double too.
double can hold exact integers values in range +/-2^53, when you are operating in this range - you may expect exact values.
Javascript has a constant, Number.MAX_SAFE_INTEGER which is the highest integer that can be exactly represented.
Safe in this context refers to the ability to represent integers exactly and to correctly compare them. For example, Number.MAX_SAFE_INTEGER + 1 === Number.MAX_SAFE_INTEGER + 2 will evaluate to true, which is mathematically incorrect.
The value is 9007199254740991 (2^53 - 1) which makes a maximum of 15 digits safe.
JavaScript now has 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.
As you can see in the following blog post, JavaScript only supports 53 bit integers.
if you type in the console
var x = 11111111111111111
and then type
x
you'll get
11111111111111112
This has nothing to do with the parseFloat method.
There's also a related question here about working with big numbers in JavaScript.
Try using the unary + operator.
Like this + ("1111111111111111") + 1 = 1111111111111112

Why does string to number comparison work in Javascript

I am trying to compare a value coming from a HTML text field with integers. And it works as expected.
Condition is -
x >= 1 && x <= 999;
Where x is the value of text field. Condition returns true whenever value is between 1-999 (inclusive), else false.
Problem is, that the value coming from the text field is of string type and I'm comparing it with integer types. Is it okay to have this comparison like this or should I use parseInt() to convert x to integer ?
Because JavaScript defines >= and <= (and several other operators) in a way that allows them to coerce their operands to different types. It's just part of the definition of the operator.
In the case of <, >, <=, and >=, the gory details are laid out in §11.8.5 of the specification. The short version is: If both operands are strings (after having been coerced from objects, if necessary), it does a string comparison. Otherwise, it coerces the operands to numbers and does a numeric comparison.
Consequently, you get fun results, like that "90" > "100" (both are strings, it's a string comparison) but "90" < 100 (one of them is a number, it's a numeric comparison). :-)
Is it okay to have this comparison like this or should I use parseInt() to convert x to integer ?
That's a matter of opinion. Some people think it's totally fine to rely on the implicit coercion; others think it isn't. There are some objective arguments. For instance, suppose you relied on implicit conversion and it was fine because you had those numeric constants, but later you were comparing x to another value you got from an input field. Now you're comparing strings, but the code looks the same. But again, it's a matter of opinion and you should make your own choice.
If you do decide to explicitly convert to numbers first, parseInt may or may not be what you want, and it doesn't do the same thing as the implicit conversion. Here's a rundown of options:
parseInt(str[, radix]) - Converts as much of the beginning of the string as it can into a whole (integer) number, ignoring extra characters at the end. So parseInt("10x") is 10; the x is ignored. Supports an optional radix (number base) argument, so parseInt("15", 16) is 21 (15 in hex). If there's no radix, assumes decimal unless the string starts with 0x (or 0X), in which case it skips those and assumes hex. Does not look for the new 0b (binary) or 0o (new style octal) prefixes; both of those parse as 0. (Some browsers used to treat strings starting with 0 as octal; that behavior was never specified, and was [specifically disallowed][2] in the ES5 specification.) Returns NaN if no parseable digits are found.
Number.parseInt(str[, radix]) - Exactly the same function as parseInt above. (Literally, Number.parseInt === parseInt is true.)
parseFloat(str) - Like parseInt, but does floating-point numbers and only supports decimal. Again extra characters on the string are ignored, so parseFloat("10.5x") is 10.5 (the x is ignored). As only decimal is supported, parseFloat("0x15") is 0 (because parsing ends at the x). Returns NaN if no parseable digits are found.
Number.parseFloat(str) - Exactly the same function as parseFloat above.
Unary +, e.g. +str - (E.g., implicit conversion) Converts the entire string to a number using floating point and JavaScript's standard number notation (just digits and a decimal point = decimal; 0x prefix = hex; 0b = binary [ES2015+]; 0o prefix = octal [ES2015+]; some implementations extend it to treat a leading 0 as octal, but not in strict mode). +"10x" is NaN because the x is not ignored. +"10" is 10, +"10.5" is 10.5, +"0x15" is 21, +"0o10" is 8 [ES2015+], +"0b101" is 5 [ES2015+]. Has a gotcha: +"" is 0, not NaN as you might expect.
Number(str) - Exactly like implicit conversion (e.g., like the unary + above), but slower on some implementations. (Not that it's likely to matter.)
Bitwise OR with zero, e.g. str|0 - Implicit conversion, like +str, but then it also converts the number to a 32-bit integer (and converts NaN to 0 if the string cannot be converted to a valid number).
So if it's okay that extra bits on the string are ignored, parseInt or parseFloat are fine. parseInt is quite handy for specifying radix. Unary + is useful for ensuring the entire string is considered. Takes your choice. :-)
For what it's worth, I tend to use this function:
const parseNumber = (str) => str ? +str : NaN;
(Or a variant that trims whitespace.) Note how it handles the issue with +"" being 0.
And finally: If you're converting to number and want to know whether the result is NaN, you might be tempted to do if (convertedValue === NaN). But that won't work, because as Rick points out below, comparisons involving NaN are always false. Instead, it's if (isNaN(convertedValue)).
The MDN's docs on Comparision states that the operands are converted to a common type before comparing (with the operator you're using):
The more commonly used abstract comparison (e.g. ==) converts the operands to the same Type before making the comparison. For relational abstract comparisons (e.g., <=), the operands are first converted to primitives, then to the same type, before comparison.
You'd only need to apply parseInt() if you were using a strict comparision, that does not perform the auto casting before comparing.
You should use parseInt if the var is a string. Add = to compare datatype value:
parseInt(x) >== 1 && parseInt(x) <== 999;

Why is an integer literal followed by a dot a valid numeric literal in JavaScript?

In JavaScript it is valid to end an integer numeric literal with a dot, like so...
x = 5.;
What's the point of having this notation? Is there any reason to put the dot at the end, and if not, why is that notation allowed in the first place?
Update: Ok guys, since you mention floats and integers... We are talking about JavaScript here. There is only one number type in JavaScript which is IEEE-754.
5 and 5. have the same value, there is no difference between those two values.
I guess it is just compatibility with other C-like languages where the dot does matter.
You DO need the decimal point if you call a method on an integer:
5.toFixed(n) // throws an error
5..toFixed(n) // returns the string '5.' followed by n zeroes
If that doesn't look right, (5).toFixed(n), or 5.0.toFixed(n), will work, too.
That's a floating point number. Unlike any other language I've ever encountered, all numbers in Javascript are actually 64-bit floating numbers. Technically, there are no native integers in Javascript. See The Complete Javascript Number Reference for the full ugly story.
The correct answer in this case is, that it makes absolutely no difference.
Every number in JavaScript is already a 64bit floating point number.
The ". syntax" is only useful in cases where you can ommit the fixed part because it's 0:
.2 // Will end up as 0.2
-.5 // Will end up as -0.5
So overall it's just saving a byte, but it makes the code less readable at the same time.
What if it wouldn't be an integer, but a floating point literal?

Categories

Resources