parseInt() parses number literals with exponent incorrectly - javascript

I have just observed that the parseInt function doesn't take care about the decimals in case of integers (numbers containing the e character).
Let's take an example: -3.67394039744206e-15
> parseInt(-3.67394039744206e-15)
-3
> -3.67394039744206e-15.toFixed(19)
-3.6739e-15
> -3.67394039744206e-15.toFixed(2)
-0
> Math.round(-3.67394039744206e-15)
0
I expected that the parseInt will also return 0. What's going on at lower level? Why does parseInt return 3 in this case (some snippets from the source code would be appreciated)?
In this example I'm using node v0.12.1, but I expect same to happen in browser and other JavaScript engines.

I think the reason is parseInt converts the passed value to string by calling ToString which will return "-3.67394039744206e-15", then parses it so it will consider -3 and will return it.
The mdn documentation
The parseInt function converts its first argument to a string, parses
it, and returns an integer or NaN

parseInt(-3.67394039744206e-15) === -3
The parseInt function expects a string as the first argument. JavaScript will call toString method behind the scene if the argument is not a string. So the expression is evaluated as follows:
(-3.67394039744206e-15).toString()
// "-3.67394039744206e-15"
parseInt("-3.67394039744206e-15")
// -3
-3.67394039744206e-15.toFixed(19) === -3.6739e-15
This expression is parsed as:
Unary - operator
The number literal 3.67394039744206e-15
.toFixed() -- property accessor, property name and function invocation
The way number literals are parsed is described here. Interestingly, +/- are not part of the number literal. So we have:
// property accessor has higher precedence than unary - operator
3.67394039744206e-15.toFixed(19)
// "0.0000000000000036739"
-"0.0000000000000036739"
// -3.6739e-15
Likewise for -3.67394039744206e-15.toFixed(2):
3.67394039744206e-15.toFixed(2)
// "0.00"
-"0.00"
// -0

If the parsed string (stripped of +/- sign) contains any character that is not a radix digit (10 in your case), then a substring is created containing all the other characters before such character discarding those unrecognized characters.
In the case of -3.67394039744206e-15, the conversion starts and the radix is determined as base 10 -> The conversion happens till it encounters '.' which is not a valid character in base 10 - Thus, effectively, the conversion happens for 3 which gives the value 3 and then the sign is applied, thus -3.
For implementation logic - http://www.ecma-international.org/ecma-262/5.1/#sec-15.1.2.2
More Examples -
alert(parseInt("2711e2", 16));
alert(parseInt("2711e2", 10));
TO note:
The radix starts out at base 10.
If the first character is a '0', it switches to base 8.
If the next character is an 'x', it switches to base 16.

It tries to parse strings to integers. My suspicion is that your floats are first getting casted to strings. Then rather than parsing the whole value then rounding, it uses a character by character parsing function and will stop when it gets to the first decimal point ignoring any decimal places or exponents.
Some examples here http://www.w3schools.com/jsref/jsref_parseint.asp

parseInt has the purpose of parsing a string and not a number:
The parseInt() function parses a string argument and returns an
integer of the specified radix (the base in mathematical numeral
systems).
And parseInt calls the function ToString wherein all the non numerical characters are ignored.
You can use Math.round, which also parses strings, and rounds a number to the nearest integer:
Math.round("12.2e-2") === 0 //true

Math.round("12.2e-2") may round up or down based on the value. Hence may cause issues.
new Number("3.2343e-10").toFixed(0) may solve the issue.

Looks like you try to calculate using parseFloat, this will give you the correct answer.
parseInt as it says, returns an integer, whereas parseFloat returns a floating-point number or exponential number:
parseInt(-3.67394039744206e-15) = -3
parseFloat(-3.67394039744206e-15) = -3.67394039744206e-15
console.log('parseInt(-3.67394039744206e-15) = ' , parseInt(-3.67394039744206e-15));
console.log('parseFloat(-3.67394039744206e-15) = ',parseFloat(-3.67394039744206e-15));

Related

why parseInt() in javascript converting "1abc" to 1?

I am trying to understand how parseInt() will work in javascript, my scenarios are
var x = parseInt("123");
console.log(x); // outputs 123
var x = parseInt("1abc");
console.log(x); // outputs 1
var x = parseInt("abc");
console.log(x); // outputs NaN
as of my observation parseInt() converts a string to integer(not really an integer of string like "12sv") when the string begins with number.
but in reality it should return NaN.
From: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/parseInt
"If the first character cannot be converted to a number, parseInt returns NaN."
From Mozilla's docs: "If parseInt encounters a character that is not a numeral in the specified radix, it ignores it and all succeeding characters and returns the integer value parsed up to that point."
So it will parse up to the first invalid character, drop the rest of the string, and return the int it managed to parse until then. If there's no valid characters it will return NaN.
parseInt()->it simply parse the provided value to its equivalent radix conversion,if specified without radix it converts to decimal equivalent.
for coercion purpose, we should avoid using parseInt,we can use Number() function instead.

Javascript evaluate number starts with zero as a decimal

I want to evaluate number starts with zero as a decimal number.
For example, let's define convertToDec
convertToDec(010) => 10
convertToDec(0010) => 10
convertToDec(0123) => 123
etc..
Because all js numbers starts with 0 are evaluated in base 8, I tried to do it like this:
function convertToDec(num){
return parseInt(num.toString(), 10);
}
But the toString function parses the number in base 8.
Any suggestions?
Thanks!
If you literally write 0010 in JavaScript, then it will be treated as an octal number. That's just how the parser works.
From MDN's docs:
Decimal integer literal consists of a sequence of digits without a leading 0 (zero).
Leading 0 (zero) on an integer literal indicates it is in octal. Octal integers can include only the digits 0-7.
Leading 0x (or 0X) indicates hexadecimal. Hexadecimal integers can include digits (0-9) and the letters a-f and A-F.
Leading 0b (or 0B) indicates binary. Binary integers can include digits only 0 and 1.
So, when you write convertToDec(0010), your browser interprets this as convertToDec(8). It's already been "converted" to an 8 since you used an "octal literal".
If you want the literal value "0010", then you'll need to use a string.
parseInt("0010", 10); // 10
You need to call convertToDec with string arguments, not numbers.
function convertToDec(num){
return parseInt(num, 10);
}
alert(convertToDec("010"));
If you give it a number as the argument, the number has already been parsed by the Javascript interpreter, the function can't get back what you originally typed. And the JS interpreter parses numbers beginning with 0 as octal.

Why does passing '1.0' to a function change it to '1' in javascript

Can someone explain to me why when pass 1.0 to a function in javascript it gets converted to 1 and how to work around this quirk?
var return_me = function(value) {
return value;
}
console.log("1.0 is returned as " + return_me(1.0));
JavaScript doesn't distinguish between int or float like other more strongly typed languages. It just has one Number type. From the ECMA specifications:
Once the exact mathematical value (MV) for a numeric literal has been determined, it is
then rounded to a value of the Number type. If the MV is 0, then the
rounded value is +0; otherwise, the rounded value must be the Number
value for the MV (as specified in 8.5), unless the literal is a
DecimalLiteral and the literal has more than 20 significant digits, in
which case the Number value may be either the Number value for the MV
of a literal produced by replacing each significant digit after the
20th with a 0 digit or the Number value for the MV of a literal
produced by replacing each significant digit after the 20th with a 0
digit and then incrementing the literal at the 20th significant digit
position. A digit is significant if it is not part of an ExponentPart
and
it is not 0;
or there is a nonzero digit to its left and there is a nonzero digit, not in the ExponentPart, to its right.
A conforming
implementation, when processing strict mode code (see 10.1.1), must
not extend the syntax of NumericLiteral to include OctalIntegerLiteral
as described in B.1.1.
More info on Number.
So basically, the answer is that JavaScript will display numbers that look like integers as integers and numbers that look like floats as floats.
In javascript there are six build in types of values.
string
number
boolean
null and undefined
object
symbol
These are mentioned to the book You don't know JS which I find really useful in my effort to learn javascript.
As a result js sees the var value of your function as a typeof number and understands that 1.0 is the same as 1. (in case the 1.0 was 1.9 it returns 1.9 as expected).
Now if you want to keep these decimals (even if there are zero digits) you could pass the value as a string.
console.log("1.0 is returned as " + return_me("1.0"));

Javascript, why treated as octal

I'm passing as parameter an id to a javascript function, because it comes from UI, it's left zero padded. but it seems to have (maybe) "strange" behaviour?
console.log(0000020948); //20948
console.log(0000022115); //9293 which is 22115's octal
console.log(parseInt(0000022115, 10)); // 9293 which is 22115's octal
console.log(0000033959); //33959
console.log(20948); //20948
console.log(22115); //22115
console.log(33959); //33959
how can I make sure they are parsing to right numebr they are? (decimal)
EDIT:
just make it clearer:
those numbers come from the server and are zero padded strings. and I'm making a delete button for each one.
like:
function printDelButton(value){
console.log(typeof value); //output string
return '<img src="images/del.png">'
}
and
function printDelButton(value){
console.log(typeof value); //output numeric
console.log(value); //here output as octal .... :S
}
I tried :
console.log(parseInt(0000022115, 10)); // 9293 which is 22115's octal
and still parsing as Octal
If you receive your parameters as string objects, it should work to use
parseInt(string, 10)
to interpret strings as decimal, even if they are beginning with 0.
In your test, you pass the parseInt method a number, not a string, maybe that's why it doesn't return the expected result.
Try
parseInt('0000022115', 10)
instead of
parseInt(0000022115, 10)
that does return 221115 for me.
If you start it with a 0, it's interpreted as an Octal number.
See http://www.hunlock.com/blogs/The_Complete_Javascript_Number_Reference#quickIDX2
Note the article's warning here:
You should never precede a number with a zero unless you are
specifically looking for an octal conversion!
Consider looking here for ideas on removing the leadings 0s:
Truncate leading zeros of a string in Javascript
Leading 0s indicate that the number is octal.
parseInt parses a string containing a number.
parseInt(0000022115, 10) passes a numeric literal. The literal is parsed in octal by the JS interpreter, so you're passing a raw numeric value to parseInt.
Unless you can intercept a string version of this number, you're out of luck.
That being said, if you can get a string version of your octal (calling toString() won't help), this will work:
parseInt(variable_string.replace(/^0+/, ''), 10);
Try
/^[0]*([1-9]\d)/.exec(numberFromUI)[0]
That should give you just the numbers stripping the zeros (if you have to support decimals, you'll need to edit to account for the '.', and of course ',' is fun too... and I really hope you don't have to handle all the crazy different ways Europeans write numbers! )
If number came from server as zero padded string then use +"0000022115"
console.log(+"0000022115")
if (021 < 019) console.log('Paradox');
JS treat zero padded numbers like octal only if they are valid octal - if not then it treat it as decimal. To not allow paradox 'use strict' mode
'use strict'
if (021 < 019) console.log('Paradox');

How does parseFloat() work when the string contains non-numeric characters?

I'm having a problem when executing parseFloat() - I don't understand why it produces the following outputs:
document.write(parseFloat("6e2") + "<br />"); //output is 600 why?
document.write(parseFloat("6b2") + "<br />"); //output is 6 why?
document.write(parseFloat("6c2") + "<br />"); //output is 6 why?
Could you tell me how the script is working?
6e2 produces 600 because it's treating your input as scientific notation.
6e2 == 6 x 102 == 600
The other two produce 6 because parseFloat parses the 6, then gets to input it isn't able to convert to a number, so it stops, and returns the result found so far.
Per MDN:
parseFloat is a top-level function and is not associated with any
object.
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.
If the first character cannot be converted to a number, parseFloat
returns NaN.
For arithmetic purposes, the NaN value is not a number in any radix.
You can call the isNaN function to determine if the result of
parseFloat is NaN. If NaN is passed on to arithmetic operations, the
operation results will also be NaN.
parseFloat() function determines if the first character in the specified string is a number. If it is number then it parses the string until it reaches the end of the number, and it returns the number as a number, not as a string.
so parseFloat("6b2") returns 6.
so parseFloat("6c2") returns 6.
For the first one, it is because it treats e as an exponent symbol (^)
The other two are only 6 because it ignores the rest once the numbers have ended

Categories