Uczymy się konwersji binarnych na dziesiętne wykorzystując zapis 2s complement, jedyny słuszny gdzie nie ma ujemnego zera. Do dzieła.
Jak działa twos complement:
- Jeżeli pierwsza z lewej to 0 to dla reszty wylicz wartość jak dla unsigned integer
- Jeżeli pierwsza z lewej to 1 to:
- Dla reszty wylicz wartość
- Dodaj 1
- Pomnóż przez -1 pamiętając, że chcesz ujemną
Ogarnijmy funkcję 1s compelemnt z poprzedniego przykładu:
function bin2decOnes(binArr){
let sign = binArr[0];
function onesComplement(binArr){
return binArr.map((n) => {
return n === 0 ? 1 : 0
});
}
function _bin2dec(binArr){
let base = 2;
let position = 0;
let weight;
let decimalNumber = 0;
while(binArr.length > 0){
let lastDigit = binArr.pop();
weight = Math.pow(base, position);
decimalNumber += lastDigit * weight;
position++;
}
return decimalNumber;
}
if(sign === 0)
return _bin2dec(binArr.slice(1));
return -1 * bin2decOnes(onesComplement(binArr));
}
Ok, fajnie, metodą prób i błędów możemy zbudować 2s compelement:
function bin2dec2s(binArr){
let sign = binArr[0];
function onesComplement(binArr){
return binArr.map((n) => {
return n === 0 ? 1 : 0
});
}
function _bin2dec(binArr){
let base = 2;
let position = 0;
let weight;
let decimalNumber = 0;
while(binArr.length > 0){
let lastDigit = binArr.pop();
weight = Math.pow(base, position);
decimalNumber += lastDigit * weight;
position++;
}
return decimalNumber;
}
if(sign === 0)
return _bin2dec(binArr.slice(1));
return -1 * bin2dec2s(onesComplement(binArr)) -1;
}
Ta funkcja nie jest czytelna, natomiast zobaczmy, czy spełnia swoje przeznaczenie:
console.log(bin2dec2s([1,1,0,1]));
//-3
console.log(bin2dec2s([0,0,1,1]));
//3
0011 to 3 bo 011 to 3.
1101… 0010 to 2. Dodaj 1 to 3. Razy -1 to -3.
Okej, fajnie, ale nieczytelnie. My tam odejmujemy, nie dodajemy. Nie idzie się w tym połapać:
function bin2dec2s(binArr){
let sign = binArr[0];
function onesComplement(binArr){
return binArr.map((n) => {
return n === 0 ? 1 : 0
});
}
function _bin2dec(binArr){
let _sign = binArr[0];
if(_sign === 1)
binArr = onesComplement(binArr);
let base = 2;
let position = 0;
let weight;
let decimalNumber = 0;
while(binArr.length > 1){
let lastDigit = binArr.pop();
weight = Math.pow(base, position);
decimalNumber += lastDigit * weight;
position++;
}
if(_sign === 0)
return decimalNumber;
return decimalNumber + 1;
}
if(sign === 0)
return _bin2dec(binArr);
return -1 * _bin2dec(binArr);
}
console.log(bin2dec2s([1,1,0,1]));
//-3
console.log(bin2dec2s([0,0,1,1]));
//3
No tu już lepiej. Czyli:
- 0 na początku? Ok, w _bin2dec olewamy 0 po lewej i wyliczamy tradycyjnie resztę
- 1 na początku? _bin2dec zrobi podmianę bitów, wyliczy dla reszty cyfr liczbę i doda 1
- Jak była dodatnia to zwróć _bin2dec
- Jak miała 1 na początku to musi być ujemna
Polecam to sobie z kartką papieru wyliczyć. Inaczej nigdy tego nie zrozumiemy.
A jest to dużo łatwiejsze, niż nauka Reacta, gdy się nie wie, czym jest funkcja bind albo eventy w JS.
Albo nauka tailwinda/bootstrapa, gdy się zwykłego CSS nie ogarnia. Dzisiaj wszyscy programiści tacy…