Piszemy funkcję, która sprawdzi, czy podana liczba posiada tylko jedną „jedynkę” w swojej reprezentacji binarnej. Do dzieła.

Ok, przypomnę poprzednią lekcję:

function countTrailingZeros(num){

    let cnt = 0;
    let flag= 1;

    
    while((num & flag) === 0){
        cnt++;
        flag = flag << 1;
    }

    return cnt;
}

console.log(countTrailingZeros(8)); //3
console.log(countTrailingZeros(9)); //0
console.log(countTrailingZeros(1)); //0
console.log(countTrailingZeros(16)); //4
console.log(countTrailingZeros(6)); //1

Tu mamy zera po prawej wyliczane. A zera po lewej? W Int32?

Proszę:

console.log(Math.clz32(8));// 28
console.log(countTrailingZeros(8)); //3

Jak nietrudno się domyślić, liczba zawierająca tylko jedną jedynkę będzie miała liczbę zer w int32 równą 31. Mamy patent na zera po prawej i po lewej?

Mamy. Niewiele więcej potrzebujemy:

function singleOneInBinary_bad(number){
      
    function countTrailingZeros(num){

        let cnt = 0;
        let flag= 1;
    
        
        while((num & flag) === 0){
            cnt++;
            flag = flag << 1;
        }
    
        return cnt;
    }

    return (countTrailingZeros(number) + Math.clz32(number)) === 31;
}


console.log(singleOneInBinary_bad(8)); //true
console.log(singleOneInBinary_bad(4)); //true
console.log(singleOneInBinary_bad(2)); //true
console.log(singleOneInBinary_bad(1)); //true
console.log(singleOneInBinary_bad(9)); //false
console.log(singleOneInBinary_bad(6)); //false

Ok, a da się inaczej? Zobaczmy na coś takiego:

function valuesInBinary_v2(num){
    return Array.from({length: num}, (_, i) => {
        return 1 * Math.pow(2, num-1-i);
    });
}

console.log(valuesInBinary_v2(8));
//[ 128, 64, 32, 16, 8, 4, 2, 1 ]

To są wartości dla cyfr binarnych robiliśmy już to. Pobawmy się tym:

for(const val of valuesInBinary_v2(8)) {
    console.log(val, Math.log2(val));
}
// 128 7 
// 64 6 
// 32 5 
// 16 4 
// 8 3 
// 4 2 
// 2 1 
// 1 0

Jak widać każda daje normalny logarytm. Pomajstrujmy przy tym:

for(const val of valuesInBinary_v2(8)) {
    console.log(val-1, Math.log2(val-1));
}

// 127 6.9886846867721655 
// 63 5.977279923499917 
// 31 4.954196310386875 
// 15 3.9068905956085187 
// 7 2.807354922057604 
// 3 1.584962500721156 
// 1 0 
// 0 -Infinity

Teraz już powinniśmy rozumieć, że liczba z jednym 1 w binarnym będzie miała którąś z potęg 2 jako wartość. To jest ta liczba daje normalny logartym 2.

Czyli nasze sprawdzenie wygląda tak:

function singleOneInBinary(num){
    return Number.isInteger(Math.log2(num));
}

console.log(singleOneInBinary(8)); //true
console.log(singleOneInBinary(4)); //true
console.log(singleOneInBinary(2)); //true
console.log(singleOneInBinary(1)); //true
console.log(singleOneInBinary(9)); //false
console.log(singleOneInBinary(6)); //false

O logarytmach było w poprzednich lekcjach.