JavaScript
 Computer >> コンピューター >  >> プログラミング >> JavaScript

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」 です。コードの動作は次の通りです。

  1. toString(2) で数値を2進数の文字列に変換し、split('') で1文字ずつの配列に分解します。
  2. 桁数が奇数の場合は先頭に 0 を追加し、隣接ペアが崩れないように桁数を偶数に調整します。
  3. forループで2つおきに要素を走査し、分割代入 [arr[i], arr[i + 1]] = [arr[i + 1], arr[i]] によって隣接するビットを交換していきます。
  4. 交換後の配列を 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

こちらの方法は文字列への変換や配列操作が不要なため、より簡潔で高速に動作するのがメリットです。

  1. 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関数を作成する必

  2. C#で2進数を10進数に変換する方法を解説

    C#で2進数を10進数に変換する方法はいくつかありますが、ここではwhileループを使った基本的なアルゴリズムを紹介します。この方法では、入力された2進数の各桁の余り(剰余)を求め、その余りに基数(2のべき乗)を掛けて順次加算していくことで、10進数の値を算出します。変換の仕組み2進数「1010」を例に考えてみましょう。各桁を右から順に取り出し、それぞれに1、2、4、8という基数を掛けて合計します。具体的には以下のような流れになります。最下位の桁(余り)を val % 10 で取得する余りに現在の基数値を掛けて10進数の結果に加算するval / 10 で処理済みの桁を取り除く基数値を2倍して次