Moox
Moox

Reputation: 1117

Why do strings sometimes get changed to numbers in javascript?

I have this code:

function getSessionGUID() {
   return (S4()+S4());
}

function S4() {
   return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
}

It clearly returns a string, but if you run it a bunch of times, you can notice that it sometimes returns infinity.

for (var i = 0; i < 100000; i++){ if(getSessionGUID() == Infinity) console.log("INFINITY"); }
871 x INFINITY

I then noticed that if you remove the |0, it solves the problem:

function S4() {
   return (((1+Math.random())*0x10000)|0).toString(16).substring(1);
}

Results:

for (var i = 0; i < 100000; i++){ if(getSessionGUID() == Infinity) console.log("INFINITY"); }
undefined

Why does this happen? In both cases the value is changed into a string.

Upvotes: 1

Views: 719

Answers (5)

Anirudh Ramanathan
Anirudh Ramanathan

Reputation: 46728

JavaScript is dynamically typed. There isn't an integer, floating point. String data type. All of that conversions is done internally depending on the context.

The + could be string concatenation or addition depending on context.

Edit: Apologies. Too late. But it was the == performing the conversion to number when comparing against infinity. In some cases, you generated valid numbers.

Upvotes: 2

jbabey
jbabey

Reputation: 46647

You are generating hexidecimal strings.

When you use the == operator, the interpreter tries to coerce the two values to the same data type. When comparing strings to Infinity, that intermediate data type is Number. When those strings contain the letter "e" (a valid hexidecimal digit) and they're coerced to a Number, javascript interprets this as 10^x which ends up as some huge number.

Numbers in javascript are 8 bytes, so anything larger than 1.7976931348623157e308 is considered equal to Infinity.

The easiest way to fix this is to change your == to === so the string doesn't get coerced to a number.

if(getSessionGUID() === Infinity)

http://jsfiddle.net/Uhkxm/

Upvotes: 3

John Dvorak
John Dvorak

Reputation: 27287

This test reveals the answer:

for (var i = 0; i < 100000; i++){
  var x=getSessionGUID();
  if(x == Infinity) console.log(x); }
}

It logs values like 61e93284 or 1413e390

These values are valid numbers and they are way too big for the Number type, so they get cast as Infinity when interpreted as a number.

If you replace == with === in the test, no conversion occurs and nothing is logged. The conversion is caused by the == operator.

Upvotes: 2

Moox
Moox

Reputation: 1117

I think I figured it out. There's actually nothing wrong in all of this, except on my test code.

If you take this string "11e51354", you can get it to assert to true since Javascript checks for all the types that could make it equal to true.

"11e51354" == Infinity # True

The right test would be:

"11e51354" === Infinity # False

It's still a string, but somehow while I was sending it through a GET request, it was being transformed into a number type which gave Infinity.

Upvotes: 2

NiLL
NiLL

Reputation: 13843

If you really need a number type, you always could use following.
console.log(Number("1"));

Upvotes: 0

Related Questions