JavaScriptで数値の隣接する2進ビットを入れ替えて新しい数値を生成する方法
問題
数値を1つ受け取るJavaScript関数を書く必要があります。
この関数は、引数として渡された数値を2進表現に変換し、隣接するビット同士を入れ替えて新しい2進数を作り上げます。最後に、その新しい2進数に対応する10進数の値を返します。
コード例
以下がそのコードです −
const num = 13;
const swapBits = (num) => {
let arr = num.toString(2).split('');
if(arr.length % 2){
arr.unshift(0);
}
for(let i = 0; i < arr.length - 1; i = i + 2) {
[arr[i], arr[i + 1]] = [arr[i + 1], arr[i]];
}
return +('0b' + arr.join(''));
}
console.log(swapBits(num));
出力
14
処理の流れと解説
ここでは例として num = 13 を考えます。13 の2進表現は 「1101」 です。コードの動作は次の通りです。
toString(2)で数値を2進数の文字列に変換し、split('')で1文字ずつの配列に分解します。- 桁数が奇数の場合は先頭に
0を追加し、隣接ペアが崩れないように桁数を偶数に調整します。 - forループで2つおきに要素を走査し、分割代入
[arr[i], arr[i + 1]] = [arr[i + 1], arr[i]]によって隣接するビットを交換していきます。 - 交換後の配列を
join('')で連結し、先頭に'0b'を付けた上で単項プラス演算子を使って10進数へ変換して返します。
「1101」の場合、前半の「1」と「1」は入れ替えても変わりませんが、後半の「0」と「1」を入れ替えると「10」になります。結果として得られる「1110」は10進数で 14 であり、これが出力として返されます。
補足:ビット演算を使った別解
文字列を経由せず、ビット演算だけでも同じ処理を実現できます。マスク 0xAAAAAAAA(…1010) と 0x55555555(…0101) で交互のビット列をそれぞれ取り出し、片方を右へ1ビット、もう片方を左へ1ビットシフトしてORで結合すれば、隣接ビットの交換が一度に行えます。
const swapBits = (num) => {
return ((num & 0xAAAAAAAA) >> 1) | ((num & 0x55555555) << 1);
}
console.log(swapBits(13)); // 14
こちらの方法は文字列への変換や配列操作が不要なため、より簡潔で高速に動作するのがメリットです。
-
JavaScriptで配列内の最長の「山」部分配列の長さを求める方法
山(マウンテン)部分配列とは配列 arr の(連続した)部分配列 sub が「山」と呼ばれるのは、以下の性質を満たす場合です。sub.length >= 3 であることある 0 < i < sub.length - 1 が存在し、sub[0] < sub[1] < ... < sub[i] > sub[i+1] > ... > sub[sub.length - 1] となること。つまり、一度増加していき頂点に達した後、減少に転じる形状を持つこと問題数値の配列 arr を第一引数(唯一の引数)として受け取るJavaScript関数を作成する必
-
C#で2進数を10進数に変換する方法を解説
C#で2進数を10進数に変換する方法はいくつかありますが、ここではwhileループを使った基本的なアルゴリズムを紹介します。この方法では、入力された2進数の各桁の余り(剰余)を求め、その余りに基数(2のべき乗)を掛けて順次加算していくことで、10進数の値を算出します。変換の仕組み2進数「1010」を例に考えてみましょう。各桁を右から順に取り出し、それぞれに1、2、4、8という基数を掛けて合計します。具体的には以下のような流れになります。最下位の桁(余り)を val % 10 で取得する余りに現在の基数値を掛けて10進数の結果に加算するval / 10 で処理済みの桁を取り除く基数値を2倍して次