Nick
Nick

Reputation: 2907

parse integer with javascript using parseInt and a radix

I am doing an online test and it asks me to write basic javascript code.

It asks me to parse a numberic string and convert it to a number of a different base. It needs me to return -1 if for whatever reason the conversion cannot be done.

I have written this:

function convert(strNumber, radix) {
     var result = parseInt(strNumber, radix);
     if(isNaN(result))
     {return -1;}
     return result;
}

Then it runs my code through various tests and all pass. Except one.

Apparently convert("ASD", 15) should be invalid according to the test and it expects it to be -1. But Javascript happily converts it to number 10

I tried various things such as to add a try{}catch{} block and other things, but javascript never complains about converting "ASD" to base 15.

Is the test wrong, or is parseInt wrong?

By the way strNumber can be any base under 36. So for instance:

convert("Z", 36) is 35

Upvotes: 2

Views: 940

Answers (3)

MaxZoom
MaxZoom

Reputation: 7753

As per official documentation the parseInt function behaves as following

For radices above 10, the letters of the alphabet indicate numerals greater than 9. For example, for hexadecimal numbers (base 16), A through F are used.

and

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.

Thus to prevent invalid arguments from being parsed they have to be validated first

  function convert(strNumber, radix) {
 if (isValidRadix(radix) && isValidInteger(strNumber, radix))
   return parseInt(strNumber, radix);
  
 return -1;
}

function isValidInteger(str, radix) {
  var letters = ['0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'].slice(0,radix);
  str = str.toUpperCase();
  for (var i=0; i<str.length; i++) {
    var s = str.charAt(i);
    if (letters.indexOf(s) == -1) return false;
  }
  return true;
}

function isValidRadix(radix) {
  // 16 up to HEX system
  return radix > 0 && radix <= 16;
}
 
console.log(convert("ASD", 15));
console.log(parseInt("ASD", 15));
console.log(convert("AAA", 15)); 

Upvotes: 1

epascarello
epascarello

Reputation: 207521

As I stated in the comment, parseInt will convert up to the point where it fails. So "A" is valid in that radix and "S" is not. So you would need to add a check.

var nums = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ".substr(0, radix)
var re = new RegExp("^[" + nums + "]+$","i")
if (!re.test(strNumber)) {
   return -1
}

Upvotes: 1

Colin D
Colin D

Reputation: 3109

parseInt is behaving normally and is converting the letter A into 10 in base 15 (similar to how hex uses A for the number 10). The S and D are discarded, as parseInt accepts this type of malformed input.

From the parseInt documentation:

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.

Upvotes: 1

Related Questions