JavaScript supports different number bases. Bases 2, 8, 10 and 16 are easily written as:
Number(0b10) //2
Number(0o10) //8
Number(10) //10
Number(0x10) //16
Now I want to enter a 4 digit number from 0000-9999 the problem is that in JavaScript not only 0oXX is octal, but also numbers with leading 0's (if it can). Is there any way to determine the "real" base 10 original input, without using a string input?
Example:
Number(010) == Number(0o10) //would be true
There is now way to force JS to treat Number(010) as decimal.
When you write 010 - it's octal literal. But in strict mode 0-prefixed are not allowed.
"use strict"
010.toString()
//Uncaught SyntaxError: Octal literals are not allowed in strict mode.
"use strict"
0o10.toString()
"8"
So it seems to me, that you'll have to use text input and parse it to achieve your goal.
Related
I have a array like this.
var elements=[5614,6619,7220,7320,7830,8220,0111,0112,0113,0142,0149]
Am converting every element to string so as to use with jquery autocomplete.
Am using .map function to do this.
elements = elements.map(String);
output is
["5614", "6619", "7220", "7320", "7830", "8220", "73", "74", "75", "98", "149"]
Function is taking 0111,0112,0113,0142 all these values as Octal values and converting them to decimal.
I don't want this conversation and want to preserve leading Zero also , How can I do this , please help.
Function is taking 0111,0112,0113,0142 all these values as Octal values and converting them to decimal.
It's not the function doing that, it's this:
var elements=[5614,6619,7220,7320,7830,8220,0111,0112,0113,0142,0149]
In loose mode, if you start a number with a 0 followed by a series of octal digits, it's octal. That's why 010 === 8 is true:
console.log(010 === 8); // true
And heaven help us, but if you have a 0 followed by a number with non-octal decimal digits (8 or 9), it's decimal, which is why 011 === 09 and 9 === 09 are true:
console.log(011 === 09); // true
console.log(9 === 09); // true
The solution is:
Use strict mode ("use strict";). Both legacy octal literals (010) and legacy non-octal decimal literals (08) are disallowed in strict mode. (If you need to write octal, you can, with the newer 0o10 format — that's the number eight.)
Don't write leading zeros on numbers (with the possible exception of a 0 just prior to a . in a fractional number less than one)
You can't fix elements after the fact (because it's impossible to know, once they're numbers, which ones were incorrectly written in octal), you have to fix it at the point you're creating it, e.g.:
var elements=[5614,6619,7220,7320,7830,220,111,112,113,142,149]
This question already has answers here:
JavaScript - Preventing octal conversion
(3 answers)
Javascript, why treated as octal
(6 answers)
Why JavaScript treats a number as octal if it has a leading zero
(3 answers)
Closed 3 years ago.
In reviewing parseInt(string, radix) in:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt
all 13 examples make perfect sense except for this one.
According to one example, parseInt(015, 10) will return 13. This makes sense assuming that numericals that begin with 0 are treated as an octal, regardless of the 10 that appears in the radix position.
So if the octal is specified as it is in the question header:
parseInt(021, 8)
Then why wouldn't this be 17 (vs. 15 per the Mozilla documentation and in my tests in jsfiddle?
Any insight would be appreciated.
This is because 0n is octal notation in javascript, just like Oxn is hex notation:
console.log(021 === 0x11 && 021 === 17);
So what you wrote got evaluated as parseInt(17, 8);
Then this 17 number gets coerced to the string "17" and the result is 15.
console.log(parseInt(17, 8))
Note that all this would not have happened in strict mode, where 0n notation has been deprecated:
(function(){
"use strict";
// Syntax Error
console.log(parseInt(015, 8))
})();
The first argument of parseInt should be a string. The same MDN link says:
The value to parse. If the string argument is not a string, then it is converted to a string (using the ToString abstract operation).
You can see that this works as expected:
console.log(parseInt("021", 8))
The problem in your tests is that you're using a number, not a string. When you use 021 as a number, as you already knows (when you said "numericals that begin with 0 are treated as an octal"), it gets converted to "17":
console.log(021.toString())
And that gives you the result you're seeing:
console.log(parseInt("17", 8))
When you type 021 then this is valid octal number and because prefix 0 JS convert it to decimal 17. But if you type not valid octal number e.g. 019 then JS will NOT convert it but treat as decimal
console.log(021) // octal
console.log(019) // not octal
if( 021 < 019 ) console.log('Paradox');
I notice that strict equal operator returns true if the operands are equal and of the same type.
But, if I do this
01000 == 512; // returns true
01000 === 512; // returns true
or
0o535 == 349; // returns true
0o535 === 349; // returns true
Do they have the same value and type?
Because 01000, 512, 0o535, and 349 are all numbers. 01000 and 512 are the same value written different ways (a "legacy" octal literal and a decimal literal); so are 0o535 and 349 (a new-style octal literal and a decimal literal). The form of literal you use makes no difference to the value or type of what it creates. Similarly, 'foo' === "foo" is true, even though I use the single-quoted string literal in one and the double-quoted string literal in the other.
About the two kinds of octal literals:
01000 is a "legacy" octal literal, indicated by just the leading zero. JavaScript engines in web browsers are required (as of ES2015) to support them in loose mode, and to not support them in strict mode (e.g., "use strict"). (Note that loose mode and strict mode have nothing to do with loose equality and strict equality, which is a separate concept.) So in a compliant, browser-based JavaScript engine, 01000 === 512 is true in loose mode, but an error in strict mode, because legacy octal literals are not allowed in strict mode. (Prior to ES2015, supporting legacy octal literals in loose mode was not required.)
0o535 is the newer octal notation added in ES2015, indicated with the leading 0o. It's supported in both loose and strict modes by compliant JavaScript engines. But again, it's new, so older browsers won't be compliant.
If a number starts with 0, it is interpreted as octal, or base 8.
01000 in base 8 is 512 in base 10.
So they are equating to true. Because the value is anyway same.
Those are different ways of representing numbers and they're all of type "number". As an example
typeof 01000; //=> "number"
var num = 0o535;
num; //=> 349
Because they are equal and of the same type. They both are numbers. Number does not have anything like base - it's just a representation.
This is an interesting question because one may assume that === should be able to distinguish between different notations. However, this is not the case because JavaScript automatically interprets integers of different notations.
There are various numeric literals available. New notations for binary, octal, and hexadecimal are coming in from ES6.
1) decimal numbers are usually seen without a leading 0, but they can be written with one. If the next digit after the leading 0 is 8 or greater,
it is parsed as a decimal. Otherwise, it is parsed as an octal.
0800 === 800 --> decimal
0700 === 448 --> octal
0700 === 0o0700
Now for the new ES6 number features:
2) binary numbers have a leading 0b or 0B.
3) octal numbers have a leading 0o or 0O.
4) hexadecimal numbers have a leading 0x or 0X.
acturally, they have the same type :
typeof(01000) //"number"
typeof(0o535) //"number"
they are base 8 thought by js
The numbers you wrote (01000 and 0o535) are just octal representations of the numbers 512 and 349.
01000 = 0*8^0 +0*8^1 + 0*8^2 + 1*8^3 = 512
0o535 = 5*8^0 + 3*8^1 +5*8^2 = 5 + 24 + 320 = 349
javascript doesn't really care about the base you use to write your numbers.
I receive a long XML from backend. To further use the xml I convert it to JSON object using one of the standard XMLtoJSON javascript library. The issue is, some of the XML value contains number with leading zeros eg: 001072.
The problem is, when javascript library converts xml to JSON, number with leading zeros give completely different value.
For example
“001072” converts “570”
Other times it parse it correctly. For example:
“0045678” converts to 45678
The problem is how javascript handle number with zeros. I don’t know the reason of this strange behavior!!
Please suggest a solution which can parse number with zeros consistently and how can I use it with xmltojson library
This is most likely a problem with octal literals. If a number starts with a leading 0, JavaScript by default will try to parse it as an octal literal.
For this reason, you should always specify the radix parameter when calling parseInt. The library probably does not do that.
parseInt("012", 8); // 10
parseInt("012", 10); // 12
I think this is the offending line in the library, probably. Either edit the library, or edit your XML.
Octal numbers with the leading zero are on the way out. For ECMAScript5 they can still cause problems and are thus not allowed in strict mode and throw a runtime error. You really should not be using 3rd party scripts that are not in strict mode they are dangerous for way too many reasons, as you can see with the handling of the octal numbers.
As ECMAScript 6 becomes more wide spread the use of the leading zero will be pushed out all together.
Octals literals will have a '0o' prefix 0o10 === 8 can be uppercase 'o' but I am sure you can see this will be a hassle. ES6 will also formalise the binary format with the prefix 0b1000 === 8 though most browsers have supported it for some time. Hex has also been around for a while 0x08 == 8
The reason some numbers with leading zeros are decmil and some octal is dependent on what digits are in the number. Octal does not use the digits 8 and 9 so any number that have these digits can not be octal.
This question already has answers here:
Prefix zero changes output in number addition [duplicate]
(2 answers)
Closed 9 years ago.
I have encountered a very weird issue with my JavaScript program. I have fount that JavaScript for some reason changes 040000 into 16384! [Example] Does anyone know why JavaScript is doing this?
It's because in js, number literals prepended with 0 are considered octal (base 8)
For example
010 == 8
In your example 040000 is really 4*8*8*8*8 = 16384 because in octal each 0 in the right multiplies the value by 8.
EDIT: Bonus:
If the leading 0 is in a string representation, (for example, if it was introduced by the user), and you want to avoid converting to octal, specify the base (aka radix) with value 10 in the parseInt method call, like this
var number = parseInt("040000", 10); //number will be 40000 ;)
In recent browsers, the radix is 10 by default, but not in old browsers, so if you want maximum compatibility also, always specify the radix parameter (usually 10).
Cheers
Because javascript thinks its in OCTAL format
Explanation:-
Javascript (like most programming languages) allows us to work directly with both octal and hexadecimal numbers, all we need is a way to tell which number base we are using when we specify a number. To identify octal and hexadecimal numbers we add something to the front of numbers using those bases to indicate which base we are using. A leading 0 on the front of a number indicates that the number following is octal while a leading 0x indicates a hexadecimal number. The decimal number 18 can therefore also be represented as 022 (in octal) and 0x12 (in hexadecimal). We don't put a special symbol on the front of decimal numbers so any number that doesn't start with 0 or 0x is assumed to be decimal.
So its same in your case
040000(base8)=16384(base10)