Filip neskoski
Filip neskoski

Reputation: 23

javascript program to convert binary to decimal and back

I have tried this

function binToDec(num) {
    let dec = 0; 
    for(let i = 0; i < num.length; i++) {
        if(num[num.length - (i + 1)] === '1') {
            dec += 2 ** i;
        }
    }
    return dec;
}

console.log(binToDec('1010'));

this code is not mine and it works but i want to know how it converts the binary number to decimal and it will be very helpful is you could tell me another way to do it.

I have also tried this

function binToDec(num) {
    let bin = parseInt(num, 2);
    return bin;
}
console.log(binToDec(1010));

I know this also work but i am not looking for this answer.

thank you for your help.

Upvotes: 1

Views: 4282

Answers (2)

user1636522
user1636522

Reputation:

Explanation

Think of how base 10 works.

909 = 900 + 9
    = (9 *   100) + (0 *    10) + (9 *     1)
    = (9 * 10**2) + (0 * 10**1) + (9 * 10**0)

As you can see, a natural number in base 10 can be seen as a sum where each term is in the form of:

digit * base**digit_position

This is true for any base:

base 2 : 0b101 = (0b1 * 2**2) + (0b0 * 2**1) + (0b1 * 2**0)
base 16 : 0xF0F = (0xF * 16**2) + (0x0 * 16**1) + (0xF * 16**0)

Therefore, here is a possible abstraction of a natural number:

function natural_number (base, digits) {
  var sum = 0;
  for (var i = 0; i < digits.length; i++) {
    digit = digits[i];
    digit_position = digits.length - (i + 1);
    sum += digit * base**digit_position;
  }
  return sum;
}
> | natural_number(2, [1, 0, 1]) // 1 * 2**2 + 1 * 2**0
< | 5
> | natural_number(10, [1, 0, 1]) // 1 * 10**2 + 1 * 10**0
< | 101
> | natural_number(16, [1, 0, 1]) // 1 * 16**2 + 1 * 16**0
< | 257

Your own function takes only binary numbers (base 2). In this case digit can be either 0 or 1, that's all. We know that it's useless to multiply something by 0 or 1, so the addition can be replaced with:

if (digit === 1) {
  sum += 2**digit_position;
}

Which is the equivalent of:

if (num[num.length - (i + 1)] === '1') {
  dec += 2 ** i;
}

Do you get it? :-)

Alternative

You don't feel confortable with the exponentiation operator (**)? There is a workaround. Did you ever notice that multiplying a number by 10 is nothing more than shifting its digits one time to the left?

909 * 10 = 9090

Actually, shifting a number to the left boils down to multiplying this number by its base:

number *= base

This is true for any base:

base 2 : 0b11 * 2 = 0b110
base 16 : 0xBEE * 16 + 0xF = 0xBEE0 + 0xF = 0xBEEF

Based on this, we can build an algorithm to convert an array of digits into a number. A trace of execution with [9,0,9] in base 10 as input would look like this:

init  |   0 | n = 0
add 9 |   9 | n += 9
shift |  90 | n *= 10
add 0 |  90 | n += 0
shift | 900 | n *= 10
add 9 | 909 | n += 9

Here is a possible implementation:

function natural_number (base, digits) {
  var n = 0;
  for (var i = 0; i < digits.length; i++) {
    n += digits[i];
    if (i + 1 < digits.length) {
      n *= base;
    }
  }
  return n;
}

Of course this function works the same as before, and there is a good reason for that. Indeed, unroll the for loop that computes [9,0,9] in base 10, you get this:

return ((0 + 9) * 10 + 0) * 10 + 9;

Then expand this expression:

((0 + 9) * 10 + 0) * 10 + 9
= (0 + 9) * 10 * 10 + 0 * 10 + 9
= 9 * 10 * 10 + 0 * 10 + 9
= 9 * 10**2 + 0 * 10**1 + 9 * 10**0

Do you recognize the equation discussed earlier? :-)

Bonus

Reverse function:

function explode_natural_number (base, number) {
  var remainder, exploded = [];
  while (number) {
    remainder = number % base;
    exploded.unshift(remainder);
    number = (number - remainder) / base;
  }
  return exploded.length ? exploded : [0];
}
> | explode_natural_number(2, 5)
< | [1, 0, 1]
> | explode_natural_number(3, 5) // base 3 (5 = 1 * 3**1 + 2 * 3**0) :-)
< | [1, 2]
> | explode_natural_number(16, natural_number(16, [11, 14, 14, 15])) // 0xBEEF
< | [11, 14, 14, 15]

String to number and number to string:

function parse_natural_number (number, base) {
  var ZERO = 48, A = 65; // ASCII codes
  return natural_number(base, number.split("").map(function (digit) {
    return digit.toUpperCase().charCodeAt(0);
  }).map(function (code) {
    return code - (code < A ? ZERO : A - 10);
  }));
}

function stringify_natural_number (number, base) {
  var ZERO = 48, A = 65; // ASCII codes
  return String.fromCharCode.apply(
    String, explode_natural_number(base, number).map(function (digit) {
      return digit + (digit < 10 ? ZERO : A - 10);
    })
  );
}
> | stringify_natural_number(parse_natural_number("48879", 10), 16)
< | "BEEF"
> | parse_natural_number("10", 8)
< | 8

More levels of abstraction for convenience:

function bin_to_dec (number) {
  return parse_natural_number(number, 2);
}

function oct_to_dec (number) {
  return parse_natural_number(number, 8);
}

function dec_to_dec (number) {
  return parse_natural_number(number, 10);
}

function hex_to_dec (number) {
  return parse_natural_number(number, 16);
}

function num_to_dec (number) {
  switch (number[0] + number[1]) {
    case "0b" : return bin_to_dec(number.slice(2));
    case "0x" : return hex_to_dec(number.slice(2));
    default : switch (number[0]) {
      case "0" : return oct_to_dec(number.slice(1));
      default : return dec_to_dec(number);
    }
  }
}
> | oct_to_dec("10")
< | 8
> | num_to_dec("010")
< | 8
> | 010 // :-)
< | 8
function dec_to_bin (number) {
  return stringify_natural_number(number, 2);
}
> | dec_to_bin(8)
< | "1000"

Upvotes: 1

Nina Scholz
Nina Scholz

Reputation: 386560

I just starts with the last character of the string and adds the value of this position to the result.

string    dec
------  -------
 1010    0
    0    0
   1     0 + 2
  0      2
 1       2 + 8
------  ------
        10

function binToDec(num) {
    let dec = 0;
    for (let i = 0; i < num.length; i++) {
        if (num[num.length - (i + 1)] === '1') {
            dec += 2 ** i;
        }
    }
    return dec;
}

console.log(binToDec('1010')); // 10

Another way is to start with the left side of the sting and

  • multiply the converted value by the base (2) and
  • add the value of the string.

The result is now the converted number. This works for all bases, as long as the value at the index is converted to a number.

function binToDec(num) {
    let dec = 0;
    for (let i = 0; i < num.length; i++) {
        dec *= 2;
        dec += +num[i];
    }
    return dec;
}

console.log(binToDec('1101')); // 13

Upvotes: 2

Related Questions