parseInt、toString與進位制的關係
今天看到一道題,[“1”,”2”,”3”].map(parseInt) ,答案會輸出什麼?
很多人會想到 [ 1, 2, 3] ,但是答案是 [ 1,NaN, NaN ]。一開始我也是懵逼的,不知道為什麼,下午查了一些資料,總算知其原因,問題出在parseInt 的引數上面,而且這種情況平時很難遇到,工作也基本用不到,下面我簡單說下。這個與進位制有關,另外後面再補充下toString的罕見用法,關於map的用法,在這裡就不介紹了,網上介紹的比較多。
parseInt
對於parseInt的基本用法,大家都知道,我們一般用他來把一個小數或字串轉換為整數。
parseInt (21.2)//返回21
parseInt(‘17’)//返回Number型別的17
另外的用法是,parseInt可以接收兩個引數,我們平常都是使用了第一個引數,但是它還有第二個引數。並且parseInt.length=2
我們看看MDN上對第二個引數的解釋:
一個2到36之間的整數值,用於指定轉換中採用的基數。比如引數”10”表示使用我們通常使用的十進位制數值系統。總是指定該引數可以消除閱讀該程式碼時的困惑並且保證轉換結果可預測。當忽略該引數時,不同的實現環境可能產生不同的結果。
文字不好形容,下面咱們就來例項解釋下:
parseInt(101,2)//返回5
parseInt(8,3 )//返回NaN
parseInt(16,3)//返回1
parseInt('dsff66',16)//返回13
看到第一個例子,大家是不是就恍然大悟了,第一個表達的意思是把2進位制101,轉化成十進位制是幾,答案就是5。
同理對於第二個例子,意思就是把3進位制8轉化成的數字是幾。那麼為什麼是NaN呢,其實很簡單,大家仔細看下,3進位制會出現8嗎?在3進位制裡面,生成最大的數是2。有一個規律,生成最大的數總比進位制數小1,比如十進位制最大的數是9等等。對於那些不可能出現的數,自動忽略,但是忽略以後就沒有數了,轉化就是NaN。
下面來看第三個例子,parseInt(16,3)
,出現最大的數字是2,那麼6就是被自動忽略掉(),所以parseInt是直接用三進位制去解析1,得到的當然是1了。
最後一個parseInt('dsff66',16)
,我們知道,平時使用parseInt,它會忽略到除數字之外的字元,但是這裡不一樣,因為十進位制最大的數字是9,但是到了十一進位制往上,最大的數字是兩位數了,這當然不行,所以從10開始往上,就用字母代替,a==10,b==11……z==35;所以這就是為什麼parseInt的第二個引數要規定在2~36了。
再看看上面這道問題,在16進制中,最大的數字是15,對應字母也就是f,超過f的字母也就超出了16進位制的解析範圍。
關於parseInt就說到這裡,下面補充下toString和進位制的關係。
toString
基本用法是用於將當前物件以字串的形式返回。
比如:
(56).toString(); //返回"56"
重要的是toString(),括號裡面可以傳參,引數代表進位制數,這個和parseInt第二個引數一樣。但是總的用法正好和parseInt反過來,一個是把多少進位制轉換成10進位制,另外一個是把十進位制轉換成多少進位制。toString屬於後者。
例子:
(5).toString(2);//返回字串"101"
上面意思就是把5轉換成2進位制是多少,結果返回一個字串。
之前看過一道演算法面試題,如下:
如何利用位操作判斷一個整數是不是2的整數次方
這道題其實思路很多,但是比較簡單的方法我感覺是先把這個數轉化為二進位制,如果是2的整數次方,那麼第一位是1,其餘都是0。如果滿足了這個,那麼這個數就是2的整數次方。我自己寫的程式碼如下,如果有誤,請指正,我就不會詳細介紹每一步了,已經說了大概思路
function a(num) {
var flag = true;
if (num==0) {
return false;
}
num = num.toString(2).split("");
for(var i=1;i<num.length;i++){
if (num[0]!=1 || num[i]==1) {
flag = false;
}
}
return flag;
}
就介紹到這裡吧,寫東西太費時間了,一兩個小時過去了。