# O.4 — Converting between binary and decimal

Consider a normal decimal number, such as 5623. We intuitively understand that these digits mean (5 * 1000) + (6 * 100) + (2 * 10) + (3 * 1). Because there are 10 decimal numbers, the value of each subsequent digit to the left increases by a factor of 10.

Binary numbers work the same way, except because there are only 2 binary digits (0 and 1), the value of each digit increases by a factor of 2. Just like commas are often used to make a large decimal number easy to read (e.g. 1,427,435), we often write binary numbers in groups of 4 bits to make them easier to read (e.g. 1101 0101).

The following table counts to 15 in decimal and binary:

Decimal Value Binary Value
0 0
1 1
2 10
3 11
4 100
5 101
6 110
7 111
8 1000
9 1001
10 1010
11 1011
12 1100
13 1101
14 1110
15 1111

Converting binary to decimal

In the following examples, we assume that we’re dealing with unsigned integers.

Consider the 8 bit (1 byte) binary number 0101 1110. Binary 0101 1110 means (0 * 128) + (1 * 64) + (0 * 32) + (1 * 16) + (1 * 8) + (1 * 4) + (1 * 2) + (0 * 1). If we sum up all of these parts, we get the decimal number 64 + 16 + 8 + 4 + 2 = 94.

Here is the same process in table format. We multiply each binary digit by its digit value (determined by its position). Summing up all these values gives us the total.

Converting 0101 1110 to decimal:

 Binary digit 0 1 0 1 1 1 1 0 * Digit value 128 64 32 16 8 4 2 1 = Total (94) 0 64 0 16 8 4 2 0

Let’s convert 1001 0111 to decimal:

 Binary digit 1 0 0 1 0 1 1 1 * Digit value 128 64 32 16 8 4 2 1 = Total (151) 128 0 0 16 0 4 2 1

1001 0111 binary = 151 in decimal.

This can easily be extended to 16 or 32 bit binary numbers simply by adding more columns. Note that it’s easiest to start on the right end, and work your way left, multiplying the digit value by 2 as you go.

Method 1 for converting decimal to binary

Converting from decimal to binary is a little more tricky, but still pretty straightforward. There are two good methods to do this.

The first method involves continually dividing by 2, and writing down the remainders. The binary number is constructed at the end from the remainders, from the bottom up.

Converting 148 from decimal to binary (using r to denote a remainder):

148 / 2 = 74 r0
74 / 2 = 37 r0
37 / 2 = 18 r1
18 / 2 = 9 r0
9 / 2 = 4 r1
4 / 2 = 2 r0
2 / 2 = 1 r0
1 / 2 = 0 r1

Writing all of the remainders from the bottom up: 1001 0100

148 decimal = 1001 0100 binary.

You can verify this answer by converting the binary back to decimal:

(1 * 128) + (0 * 64) + (0 * 32) + (1 * 16) + (0 * 8) + (1 * 4) + (0 * 2) + (0 * 1) = 148

Method 2 for converting decimal to binary

The second method involves working backwards to figure out what each of the bits must be. This method can be easier with small binary numbers.

Consider the decimal number 148 again. What’s the largest power of 2 that’s smaller than 148? 128, so we’ll start there.

Is 148 >= 128? Yes, so the 128 bit must be 1. 148 - 128 = 20, which means we need to find bits worth 20 more.
Is 20 >= 64? No, so the 64 bit must be 0.
Is 20 >= 32? No, so the 32 bit must be 0.
Is 20 >= 16? Yes, so the 16 bit must be 1. 20 - 16 = 4, which means we need to find bits worth 4 more.

Is 4 >= 8? No, so the 8 bit must be 0.
Is 4 >= 4? Yes, so the 4 bit must be 1. 4 - 4 = 0, which means all the rest of the bits must be 0.

148 = (1 * 128) + (0 * 64) + (0 * 32) + (1 * 16) + (0 * 8) + (1 * 4) + (0 * 2) + (0 * 1) = 1001 0100

In table format:

 Binary number 1 0 0 1 0 1 0 0 * Digit value 128 64 32 16 8 4 2 1 = Total (148) 128 0 0 16 0 4 0 0

Another example

Let’s convert 117 to binary using method 1:

117 / 2 = 58 r1
58 / 2 = 29 r0
29 / 2 = 14 r1
14 / 2 = 7 r0
7 / 2 = 3 r1
3 / 2 = 1 r1
1 / 2 = 0 r1

Constructing the number from the remainders from the bottom up, 117 = 111 0101 binary

And using method 2:

The largest power of 2 less than 117 is 64.

Is 117 >= 64? Yes, so the 64 bit must be 1. 117 - 64 = 53.
Is 53 >= 32? Yes, so the 32 bit must be 1. 53 - 32 = 21.
Is 21 >= 16? Yes, so the 16 bit must be 1. 21 - 16 = 5.

Is 5 >= 8? No, so the 8 bit must be 0.
Is 5 >= 4? Yes, so the 4 bit must be 1. 5 - 4 = 1.
Is 1 >= 2? No, so the 2 bit must be 0.
Is 1 >= 1? Yes, so the 1 bit must be 1.

117 decimal = 111 0101 binary.

In some cases (we’ll see one in just a moment), it’s useful to be able to add two binary numbers. Adding binary numbers is surprisingly easy (maybe even easier than adding decimal numbers), although it may seem odd at first because you’re not used to it.

Consider two small binary numbers:
0110 (6 in decimal) +
0111 (7 in decimal)

Let’s add these. First, line them up, as we have above. Then, starting from the right and working left, we add each column of digits, just like we do in a decimal number. However, because a binary digit can only be a 0 or a 1, there are only 4 possibilities:

• 0 + 0 = 0
• 0 + 1 = 1
• 1 + 0 = 1
• 1 + 1 = 0, carry a 1 over to the next column

Let’s do the first column:

```0110 (6 in decimal) +
0111 (7 in decimal)
----
1
```

0 + 1 = 1. Easy.

Second column:

``` 1
0110 (6 in decimal) +
0111 (7 in decimal)
----
01
```

1 + 1 = 0, with a carried one into the next column

Third column:

```11
0110 (6 in decimal) +
0111 (7 in decimal)
----
101
```

This one is a little trickier. Normally, 1 + 1 = 0, with a carried one into the next column. However, we already have a 1 carried from the previous column, so we need to add 1. Thus, we end up with a 1 in this column, with a 1 carried over to the next column

Last column:

```11
0110 (6 in decimal) +
0111 (7 in decimal)
----
1101
```

0 + 0 = 0, but there’s a carried 1, so we add 1. 1101 = 13 in decimal.

Now, how do we add 1 to any given binary number (such as 1011 0011)? The same as above, only the bottom number is binary 1.

```       1  (carry column)
1011 0011 (original binary number)
0000 0001 (1 in binary)
---------
1011 0100
```

Signed numbers and two’s complement

In the above examples, we’ve dealt solely with unsigned integers. In this section, we’ll take a look at how signed numbers (which can be negative) are dealt with.

Signed integers are typically stored using a method known as two’s complement. In two’s complement, the leftmost (most significant) bit is used as the sign bit. A 0 sign bit means the number is positive, and a 1 sign bit means the number is negative.

Positive signed numbers are represented in binary just like positive unsigned numbers (with the sign bit set to 0).

Negative signed numbers are represented in binary as the bitwise inverse of the positive number, plus 1.

Converting integers to binary two’s complement

For example, here’s how we represent -5 in binary two’s complement:

First we figure out the binary representation for 5: 0000 0101
Then we invert all of the bits: 1111 1010
Then we add 1: 1111 1011

Converting -76 to binary:

Positive 76 in binary: 0100 1100
Invert all the bits: 1011 0011

Why do we add 1? Consider the number 0. If a negative value was simply represented as the inverse of the positive number, 0 would have two representations: 0000 0000 (positive zero) and 1111 1111 (negative zero). By adding 1, 1111 1111 intentionally overflows and becomes 0000 0000. This prevents 0 from having two representations, and simplifies some of the internal logic needed to do arithmetic with negative numbers.

Converting binary two’s complement to integers

To convert a two’s complement binary number back into decimal, first look at the sign bit.

If the sign bit is 0, just convert the number as shown for unsigned numbers above.

If the sign bit is 1, then we invert the bits, add 1, then convert to decimal, then make that decimal number negative (because the sign bit was originally negative).

For example, to convert 1001 1110 from two’s complement into a decimal number:
Given: 1001 1110
Invert the bits: 0110 0001
Convert to decimal: (0 * 128) + (1 * 64) + (1 * 32) + (0 * 16) + (0 * 8) + (0 * 4) + (1 * 2) + (0 * 1) = 64 + 32 + 2 = 98
Since the original sign bit was negative, the final value is -98.

Why types matter

Consider the binary value 1011 0100. What value does this represent? You’d probably say 180, and if this were a standard unsigned binary number, you’d be right.

However, if this value was stored using two’s complement, it would be -76.

And if the value were encoded some other way, it could be something else entirely.

So how does C++ know whether to print a variable containing binary 1011 0100 as 180 or -76?

In case the section title didn’t give it away, this is where types come into play. The type of the variable determines both how a variable’s value is encoded into binary, and decoded back into a value. So if the variable type was an unsigned integer, it would know that 1011 0100 was standard binary, and should be printed as 180. If the variable was a signed integer, it would know that 1011 0100 was encoded using two’s complement (now guaranteed as of C++20), and should be printed as -76.

What about converting floating point numbers from/to binary?

How floating point numbers get converted from/to binary is quite a bit more complicated, and not something you’re likely to ever need to know. However, if you’re curious, see this site, which does a good job of explaining the topic in detail.

Quiz time

Question #1

Convert 0100 1101 to decimal.

Show Solution

Question #2

Convert 93 to an 8-bit unsigned binary number. Use both methods above.

Show Solution

Question #3

Convert -93 to an 8-bit signed binary number (using two’s complement).

Show Solution

Question #4

Convert 1010 0010 to an unsigned decimal number.

Show Solution

Question #5

Convert 1010 0010 to a signed decimal number (assume two’s complement).

Show Solution

Question #6

Write a program that asks the user to input a number between 0 and 255. Print this number as an 8-bit binary number (of the form #### ####). Don’t use any bitwise operators. Don’t use `std::bitset`.

Show Hint

Show Hint

Show Solution 6.1 -- Compound statements (blocks) Index O.3 -- Bit manipulation with bitwise operators and bit masks

### 456 comments to O.4 — Converting between binary and decimal

• internet_laser

Here's the solution I came up with (using a loop)

• Yolo

I tried using method 1 on a coincise and understandable manner but im stuck on how to print the values from right to left. Should i give up with this method? Any suggestions would be greatfull.

• Yolo

#edit: Forgot to mention that the numbers appear right, just in the opposite way i want to.

• TL

Whilst it is perhaps more straightforward to use method 2 instead, it can be done using method 1.

You currently have a solution that allows you to print the digits in reverse, so you might ask yourself - 1). How do I store the result I have already (instead of printing it)? and 2). Having stored it, how do I reverse it?

It’s a useful exercise to solve - hopefully that’s enough to get you on the right track.

• Yolo

Thank you very much TL. You inspired me to create a solution. For anyone who thinks that will help him, here it is.

• Cerezas

I advice you against this implementation. Method 1 has the advantage of scaling to bigger numbers, but you lose this advantage.

Instead of instantly buffering std::cout with the new bit, causing your result to be inverted, you could store your bit in a string.
Imagine initializing your result as an empty string called binaryRepresentation. Adding a new bit called newBit to this representation would only take you this one line:

Where '+' is the string concatination binary operator.
When you are done with all the divisions, binaryRepresentation is your final result ready to be buffered into std::cout.

This solution is concise but not memory efficient: string concatination causes a new string to be created.
For a memory efficient solution, you should work with an array of chars or directly with pointers (covered later in this course).

• TL

My solution to Q6, modified to sanitise input and allow the user to select whether to enter a 4, 8, 16, or 32 bit number for conversion:

• nascardriver

You can avoid the big numbers in line 27+

- Use single quotation marks for characters (' ' vs " ").
- Initialize variables with brace initialization for higher type safety.

Good job :)

• Dudz

• Dudz

Is my answer for question#5 acceptable? I first subtracted 1 from the binary numbers before inverted it because I thought adding 1 is just for decimal to binary so subtract 1 for binary to decimal with two's complement.

Question #5
Convert 1010 0010 to a signed decimal number (assume two’s complement).
bits minus 1 is 10100001
invert bits     01011110
________________________________________________
|Binary digit |0  |1  |0  |1  |1  |1  |1  |0   |
------------------------------------------------
|*Digit value |128|64 |32 |16 |8  |4  |2  |1   |
------------------------------------------------
|=Total(94)   |0  |64 |0  |16 |8  |4  |2  |0   |
````````````````````````````````````````````````
For two's complement put negative sign to the left

• nascardriver

Whether you subtract 1 and then flip or flip first and then add 1 doesn't matter, the result is the same. If you flip first, you don't have to subtract, and addition is usually easier than subtraction, at least for humans. Your answer is absolutely fine, good job!

• Dudz

Thank you nascardriver.

• Michael Okolo

I had to google into topics I am yet to learn in order to answer this, yet it is still too complicated...Please do not laugh!

• Maggie

Looking forward to learning loops :)
This was fun though. The code below is the second edit of my original solution after seeing a brilliant example submitted by Matthew E.
Cheers!

• nascardriver

Hey Maggie!

Congrats on solving the quiz!

You repeated line 10, 15 and 21. This makes code harder to maintain, because you can fix a bug in one place and forget to fix it in the repetitions. Plus you have to type more. The first attempt of fixing a repetition should be restructuring of your code. You can perform the `pow2 == 8` check first to print the space. Then print the bit unconditionally. Following that, you check for `pow2 == 1` and call `passNum`.
If you can't restructure the code, or restructuring compromises quality, move the repeated code into a function.

When you use characters, not string, use single quotation marks (In your code, ' ' vs " "). Characters are more efficient.

Line 28 is dangerous. You're modifying `num` in the assignment and again in the conditional true-case. I suppose you meant to use `num - pow2` rather than `num -= pow2`.

• RJ

Here's my answer to question 6 with the use of loops

• nascardriver

Your editor probably has an auto-formatting feature, use it. It makes your code more readable and you don't have to format by hand.
- Initialize variables with brace initialization.
- Use ++prefix unless you need postfix++. postfix++ is slower.
- `uint_fast8_t` is in the `std` namespace, use `std::uint_fast8_t`. Whenever you use something that you had to include a header for, it's probably in the `std` namespace. Some things are available without "std::", because C didn't have namespaces.

• Mikhail Dennitsov

• nascardriver

You're not using the return value of `calculation`. It should be `void`.
"calculation" is a poor name. "printBinary" or similar is more descriptive.
You don't need `result0` and `result1`. You can print `0` and `1` directly.

• Sam

Question #5 solution has a grammatical error.

Change "out" to "our"! :]

• nascardriver

Lessons amended, thanks!

• Suyash

The final question is a standard one (for anyone who has taken a programming course in college)... Usually, the standard solution is to utilize the first method of continuously dividing by 2 and printing the remainder...

And, while due to the fact, that the course has yet to introduce loops (as well as conditionals with multiple statements), I decided to implement the above approach using recursion but it made printing the binary number in the required format difficult...

Hence, I decided to use the second approach of comparing the powers of 2 with the decimal value and then, subtracting it (if necessary)... I decided to only use the concepts that have been discussed so far (in the tutorial series) to make it easier for other learners... I didn't want to confuse them by using constructs unfamiliar to them...

And, finally, keep up the great work!!

Here's my solution:

• yoozer_0

Did it like this before reading hints lol.

• koe

Hi, for the quiz I had the same solution but the problem is previous lessons did not introduce conditionals with multiple statements. Only:

So I think to be compliant with lessons the answer should be

• nascardriver

It's surprising no one else noticed it, but I couldn't find a multi-statement if in a previous lesson. Lesson updated, thanks!

• Ikenna

Hey there,
Just made a program in response to the last quiz. No bitwise operators, no bitsets. If anyone has any suggestions or ideas for improving the code that will appreciated. Thank you.

Main.cpp

Functions.h

Functions.cpp

Thanks!

• Anderson

The program works indeed. Only problem is that it returns an assertion error when user inputs 0.
The cause of this is in the generateBitVector() function. Here's one way to fix that, Simply initialize the 'bit' variable to value of 1 and then put a conditional statement 'if' in this case to make the program breaks out of the loop when the input is down to 0:

Functions.cpp

That makes it work with 0 as an input now. You're welcome.

• Anderson

Hi!

I'm still so confused about which digit of a binary figure is the sign bit.
For example :

Which is the sign bit in this case, '0' at index 0 or the '1' at index 7.
I'm sorry for asking this question but I need verification since I may have misunderstood the examples

• nascardriver

You can't set the sign bit of literals, they'll be treated as an integer of higher width rather than setting the sign bit.
The sign bit is the leftmost bit. In your example, assuming the number was treated as an 8 bit number, the sign bit is 1.

• Nick

Hello! Thanks for the tutorials, very helpful!

Just wanted to point out that I implemented question 6 with static_cast<std::bitset<8>>(getIntFromUser()) -- perhaps to make it less ambiguous what the intent of the question is, could there be wording inserted to say "implement the method 2 algorithm from above to encode a decimal number to binary" or something to that effect? That would help make the intention clearer without having to look at hints, I think.

Again, thank you for all the effort you've put into this fantastic resource! Cheers!

• nascardriver

Quiz updated to forbid the use of `std::bitset`. Thanks for pointing out the unclarity!

• knight

• nascardriver

`printandDecrementBit` returns the value of `x` or the new value of `x`, which we then store in `main`'s `x`. Return values are covered in lesson 2.2.

• Blue

Hello! Like everyone else I came up with a different solution to question 6. It works, but is it overly complicated and does it follow best practices? Thanks in advance.

functions.h

functions.cpp

main.cpp

• nascardriver

Hello!

- functions.cpp:34: You're not using `dec` after this line, don't modify `dec`. Use a regular `-`.
- functions.cpp:45-47, 53-55: Repetition. Move these lines into a function.

The rest looks good :0)

• Blue

Got it, will update accordingly. Enjoy the rest of your day!

• Alexander S.

There are no errors, but is this a valid solution to Q6 / are there general code errors I should be aware of? Thanks!

• nascardriver

Using `main` causes undefined behavior (Line 54).

- Use ++prefix instead of postfix++ unless you need postfix++.
- Use single quotation marks for characters.
- Line 29, 32 are unconditional, move them out of the `if`.
- Use your editor's auto-formatting feature.
- You're calling `powerCalc` after every loop cycle, but it will return the same number every time.
- If your program prints anything, the last thing it prints should be a line feed.

• Alexander S.

Is this better?

• nascardriver

Using `main` causes undefined behavior (Line 21, 59). You can't call `main`. You could instead call `askQuestions`. That isn't good either, but at least it's not UB. You'll learn about loops later.

You fixed some things and added a couple of new issues.

- `main`: Missing return-statement.
- Line 55: Use ++prefix instead of postfix++ unless you need postfix++.
- Line 20: You can't have 2 characters in 1 character.
- `askQuestions`'s return value is unused. Declare it `void`.
- Don't mix `std::endl` and '\n' unless you have a reason to.
- Line 47: Your program only supports numbers up to 128.

Judging by all the whitespace that went missing, I guess you auto-formatted your code. See if you can configure your editor to keep empty lines, because as it is, your code isn't easy to read.

Try applying my suggestions to make sure you understand how to do it properly. Feel free to post your revised version again.

• Alexander S.

Sorry for the deleting, thought they didn't refresh.

line 20 was a mistake when I tried reediting it so I didn't have to repaste everything.

Then the whitespace was because I repasted it after copying it from here and I noticed it after I posted and was too lazy to redo it again.

• nascardriver

Well, removing the problematic code is one way of getting rid of the problems :D
Line 71 is still using `std::endl`. Rest looks good now!
Line 62: *up to 127, sorry.

• Alexander S.

Idk what to do instead of recalling the functions if it causes problems, lol. Easier fix I guess.
I suck at remembering max values lol

• kanishkaditya shukla

hey nascardriver,

A problem arose when I was trying to implement your suggestion of moving 'int y' into main function(in my previous code given below).

What happened:-
if I move 'int y' into main function and send it to 'binconverter()' as argument then I can't change the
value of 'y' using the statement in 'binconverter()' function [ y=y-pow(2,(power-1)); ],
it simply won't work as 'y' is sent as an argument and assigned to  a perimeter in
'binconverter()' the perimeter runs out of scope for main function as the function ends.
and the changed value of 'y' is discarded as the command return to main function.hence,for the next statement
in main function( which needed the changed value ), 'y' uses the same value as perimeter again and again as perimeter
and hence, results in incorrect answer.

please let me know if I am wrong(and whats wrong), also if I am right then please suggest an alternative
method of fixing this.
sorry for annoying you.

• nascardriver

You're right. Print in `binconverter` and `return y`, have a look at the solution if you don't know how to do it. You'll later learn about references, they'll allow functions to make persistent changes to arguments.

• kanishkaditya shukla

Thanks got it now.

Tried it and it worked perfectly.
Thanks

• kanishkaditya shukla

hey alex and nascardriver,I hope you guys are having a good day.

NOTE:-i have used "using namespace std" in the program irrespective of the best practice (sorry for that) in order to keep the project short(however it didn't seem to work to be honest :-) ).

int input(int power);
char binconverter(int power);

INPUT.CPP

#include <iostream>
# include <cmath>
using namespace std;

int input(int power)
{int x;
cout << "please enter the no. to be converted into binary\n";
cin>> x;
if(x>=0)
{return x;}
else{return ((pow(2,power))+x);};
}

BIN CONVERTER.CPP

#include <iostream>
# include <cmath>
using namespace std;

int y{input(8)};

char binconverter(int power)
{

if(y<=pow(2,power)&&y>=pow(2,(power-1)))
{
y=y-pow(2,(power-1));
return '1';
}
else {
return '0';
};
}

MAIN.CPP

#include <iostream>

using namespace std;

int main()
{
int startpower{8};
/*cout <<"please enter how many bits do you want\n";
cin>> startpower;*/
char a{ binconverter(startpower)};
--startpower;
char b{ binconverter(startpower)};
--startpower;
char c{ binconverter(startpower)};
--startpower;
char d{ binconverter(startpower)};
--startpower;
char e{ binconverter(startpower)};
--startpower;
char f{binconverter(startpower)};
--startpower;
char g{ binconverter(startpower)};
--startpower;
char h{ binconverter(startpower)};
cout<<a<<b<<c<<d<<" "<<e<<f<<g<<h;
return 0;
}

hey nascardriver can you help me to figure out how can i take the user input for the number of bit and create as many as variables needed in order to assign them the value and print it.

FOR EXAMPLE:- if I want to convert a decimal number into a 16 bit binary number then in order to do this (in my program) I will have to create 16 variables(a,b,c....)and the program will become long,is there any shorter way of doing this so that the program automatically creates variables when needed.

• nascardriver

- Inconsistent formatting. Use your editor's auto-formatting feature.
- Use `std::pow` instead of `pow`.
- Don't call functions from outside of functions. (`input`).
- The last character your program prints should be a line feed to prevent mushed lines.

You're looking for dynamically allocated arrays. They're covered later.

• kanishkaditya shukla

1. what do you mean by "Don't call functions from outside of functions. (`input`)"?
whats the problem in doing so?,

(As I am working quite hard to become perfect in these topics.)

It would be very helpful if you explain these question using example (where required) instead of using some scientific word(ex:-mushed lines) as I don't know most of those yet.

• nascardriver

"mushed" is informal, it's when you take something and make it small, eg. mashed potatoes. The next line printed in the console will be appended to the last line you printed.

> whats the problem in doing so?
You don't know the order global variables get initialized in. It could happen that `input` tries to access something that doesn't exist yet.

> what should i do to remove this error from above code?
Move `y` into `main` and pass it to `binconverter`.

> The last character your program prints should be a line feed

• kanishkaditya shukla

• timbo
• Matthew E