int parseInt(string:string, radix:int)
- Produces an integer number value (or NaN)
- Leading whitespace is ignored
- Any leading characters parseInt does not understand (or expect) are ignored
- Parsing stops when it encounters a character it does not understand and it has parsed at least one character
- If radix is 0 or undefined it is assumed to be 10
- except (!) if the string starts with "0x" or "0X", then radix is assumed to be 16 instead
- if radix is negative, 1 or larger than 36, NaN is returned
- If radix is 16, the string may optionally start with "0x" or "0X"
- Note that some browsers will parse a string that starts with a zero and has no radix with radix=8 (octal), but this is not part of the specification (browser extension) and explicitly forbidden in strict mode (see Appendix C).
The specification mentions "radix-R digit" but does not define or declare it. The function to detect this to the best interpretation possible is defined below and called isRadixDigit. Again, this is not in the spec.
function parseInt(string, radix){
var inputString = ToString(string);
var S = string.trimLeft(); // regex? standard? trim()?
var sign = 1;
if (S.length != 0 && S[0] == '-') sign = -1;
if (S.length != 0 && (S[0] == '+' || S[0] == '-')) S = S.substr(1);
var R = ToInt32(radix);
var stripPrefix = true;
if (R == 0) {
R = 10;
} else {
if (R < 2 || R > 36) return NaN;
if (R != 16) stripPrefix = false;
}
if (stripPrefix) {
if (S.length >= 2 && (S.substr(0,2) == '0x' || S.substr(0,2) == '0x')) {
S = S.substr(2);
radix = 16;
}
}
// "if S contains non radix-R digits, Z is the substring of S up to the first non radix-R digit"
var Z, n=S.length,i=0;
while (n-->0) {
if (!isRadixDigit(S[i++].toLowerCase(), radix)) {
Z = S.substr(0, i);
break;
}
}
if (Z === undefined) Z = S;
if (Z == '') return NaN;
// now we actually conver the number. there's some voodoo magic here and
// a lot of stuff that may be implementation defined. however, this
// function will try to make the best of it, regardless. It does not trunc
// digits after the 20th position when radix is 10, it does not approximate.
// actual digits will retain their value, a-z (and A-Z) get their ordineal
// value in the alphabet plus 10.
var mathInt = 0, m = Z.length, n = Z.length;
while (n--) mathInt += getValueForDigit(Z[n].toLowerCase()) * Math.pow(radix, m-n); // todo: verify
mathInt = ToNumber(mathInt); // required step in this algo?
return mathInt;
}
And then the function to determine whether a character is in fact an acceptable character with current radix. Basically radix 2 through 9 are regular digits. After that digits get substituted by letters of the alphabet. So a=10, b=11, etc. This is common for hexadecimals (radix 16 uses abcdef) but is generalized up to radix 36 using the rest of the alphabet to substitute the number value by one character.
function isRadixDigit(digit, radix){
var digits = {0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,a:10,b:11,c:12,d:13,e:14,f:15,g:16,h:17,i:18,j:19,k:20,l:21,m:22,n:23,o:24,p:25,q:26,r:27,s:28,t:29,u:30,v:31,w:32,x:33,y:34,z:35};
return (digits[digit] <= radix-1);
}
Simple mapping to get value of character...
function getValueForDigit(digit){
var digits = {0:0,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,a:10,b:11,c:12,d:13,e:14,f:15,g:16,h:17,i:18,j:19,k:20,l:21,m:22,n:23,o:24,p:25,q:26,r:27,s:28,t:29,u:30,v:31,w:32,x:33,y:34,z:35};
return digits[digit];
}