Signed vs Unsigned Bit Integers: What Does It Mean and What's The Difference?
Tags: beginners, codenewbie, computerscience, todayilearned
Published: 2019-12-29 02:51:40

---
title: "Signed vs Unsigned Bit Integers: What Does It Mean and What's The Difference?"
published: true
description: "Last post in a series about binary integers for newbies"
tags: beginners, codenewbie, computerscience, todayilearned 
cover_image: https://images.unsplash.com/photo-1562343128-59e6fa1c7eb0?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1426&q=80
---

In my previous blogs, I gave an overview of what it means to work with an 8-bit, 16-bit, 32-bit, etc., number, or binary number, and how you would solve an algorithm problem that requires a certain sized bit integer without the computer science background knowledge to help make sense of it all. This post specifically tackles what exactly it means to have a signed or unsigned binary number. It won't change much the way integers are restricted when solving algorithm sets, but it will change the range you can work with dramatically. Then I'll use the same problem solved [previously](https://dev.to/aidiri/x-bit-integers-solving-with-a-range-3gm3) but accommodated to help solve for a _signed_ binary integer instead of one that isn't.

## What Does It Mean?

The biggest difference between a signed and unsigned binary number is that the far left bit is used to denote whether or not the number has a _negative sign_. The rest of the bits are then used to denote the value normally. 

This first bit, the sign bit, is used to denote whether it's positive (with a 0) or negative (with a 1). If you want to get technical, a sign bit of 0 denotes that the number is a _non-negative_, which means it can equal to the decimal zero or a positive number.

|(-/+)|2<sup>6</sup>|2<sup>5</sup>|2<sup>4</sup>|2<sup>3</sup>|2<sup>2</sup>|2<sup>1</sup>|2<sup>0</sup>|
|-|-|-|-|-|-|-|-|
|_**0**_|1|0|0|1|1|0|1|

_01001101<sub>2</sub> = +77<sub>10</sub>_

_Note: I'm using the X<sub>2</sub> notation for binary integers and the X<sub>10</sub> notation for decimal integers._

Most importantly, the first bit used to denote sign means that we have _one less bit_ to denote value. So if we have an 8-bit signed integer, the first bit tells us whether it's a negative or not, and the other seven bits will tell us what the actual number is. Because of this, we're technically working with a more limited range of numbers that can be represented; 7 bits can't store numbers as big as 8 bits could. 



## What's the difference?

### Unsigned binary numbers

To [review binary numbers](https://dev.to/aidiri/intro-to-x-bit-and-binary-integers-39lj), the ones and zeroes act like switches that metaphorically turn powers of 2 on, and then it's added up to create the decimal value. Normally, we'd "mark" a bit value with a one. 

**Example 1a:**
_Unsigned 0101<sub>2</sub> = 5<sub>10</sub>_

|2<sup>3</sup>|2<sup>2</sup>|2<sup>1</sup>|2<sup>0</sup>|
|-|-|-|-|
|0|**1**|0|**1**|


**Example 2a:**
_Unsigned 1001<sub>2</sub> = 9<sub>10</sub>_

|2<sup>3</sup>|2<sup>2</sup>|2<sup>1</sup>|2<sup>0</sup>|
|-|-|-|-|
|**1**|0|0|**1**|


### Signed binary numbers 

**Example 1b:** 
_**Signed** 0101<sub>2</sub> = +5<sub>10</sub>_

|(-/+)|2<sup>2</sup>|2<sup>1</sup>|2<sup>0</sup>|
|-|-|-|-|
|0|**1**|0|**1**|


When a signed binary number is positive or negative it's 'marked' with a 0 or 1 respectively at the first far-left bit, the sign bit. The number above doesn't change at all. It's just more explicitly a positive number. 

**Example 2b:**
_**Signed** 1001<sub>2</sub> = -7<sub>10</sub>_

|(-/+)|2<sup>2</sup>|2<sup>1</sup>|2<sup>0</sup>|
|-|-|-|-|
|1|**0**|**0**|1|


But the above binary number completely changes. And we're now representing a negative! 

### Negative binary integers

When a binary integer is negative, the _zeroes_ will now act as a "marker", instead of the ones. You would then calculate the negative binary number in the same way you would with a positive or unsigned integer, but using zeroes as markers to turn bit values "on" instead of ones and then adding the negative sign at the _end_ of your calculation.

|(-/+)|2<sup>2</sup>|2<sup>1</sup>|2<sup>0</sup>|
|-|-|-|-|
|1|**0**|**0**|1|
_**Signed** 1001<sub>2</sub> = -7<sub>10</sub>_

Going from an unsigned binary to a signed binary integer changes your end value in a couple of different ways. The first is the more obvious change in value when the first bit is used to denote sign instead of value. You can see between example 2a and 2b above that it means if you had a one at the first bit of your 4-bit integer, you're losing a value of 2<sup>3</sup> that would've been added to your end value with an unsigned bit, but is now instead used to represent a negative. With a larger bit integer, that could be an extremely larger value that you lose the ability to represent. 

Something else that isn't obvious right away is that you calculate a negative binary integer's value starting at 1, not 0. Because the decimal zero is not included in a negatively signed bit integer, we don't start counting at zero as we would when it's a positively signed bit integer. 

To explain that quirk let's compare positively and negatively signed integers. Working with a 4-bit integer, if we had four bits with a value of zero, the number would equal to 0. That's the lowest value we can have. Because a _non-negative_ signed bit means we can have a positive integer, or a 0. 

|0|0|0|0|= 0<sub>10</sub>|
|-|-|-|-|-|


A 4-bit negative integer of four bits of one values (the ones now being the "off switch"), the number would not equal 0, but -1. Which makes sense, since that's the highest decimal number we can represent while still having a negative. 

|1|1|1|1|= -1<sub>10</sub>|
|-|-|-|-|-|

But that means, when we're adding up our values to get our final decimal number, we start our counting from 1, not from 0. 

| 2<sup>x</sup> | (-/+)| 2<sup>2</sup> | 2<sup>1</sup> | 2<sup>0</sup> | _Total_ |
| --------------|-----:|----|----|----|---|
| **bit-value**         | _0_ | **1** | **1**  | 0  | |
| **2<sup>x</sup> x bit-val =** | + | **4** | **2** | 0 | **_= 6<sub>10</sub>_** |

So even if I were to perfectly flip the "switches" from the positively signed binary number above into its negative counterpart, it would not perfectly switch to its negative decimal counterpart value in the way one might expect:

| 2<sup>x</sup> | (-/+)| 2<sup>2</sup> | 2<sup>1</sup> | 2<sup>0</sup> | _Total_ |
| --------------|-----:|----|----|----|---|
| **bit-value**         | _1_ | **0** | **0**  | 1  | |
| **2<sup>x</sup> x bit-val =** | - | **4** | **2** |  | **_= -7<sub>10</sub>_** |

_Why??_

Because we're adding starting with a value of 1! And we're adding up the values that are represented in our bits before adding a negative sign at the _very_ end of our calculation. 

Here's a visual comparison of the decimal and binary equivalents that show how a 0 signed bit integer is the decimal 0<sub>10</sub> or larger, while a 1 signed bit integer is decimal -1<sub>10</sub> or smaller.

![two's complement binary vs. decimal](http://watson.latech.edu/book/assembly/images/fig11-21.png) 

### Alternatively:

Another way to calculate the negative is to keep using the ones as 'markers' and use the sign bit as a marker for the value at its corresponding power of two at a _negative_ value. This also illustrates a different way to understand what's going on in binary negative representations.

| 2<sup>x</sup> | (-/+)2<sup>3</sup>| 2<sup>2</sup> | 2<sup>1</sup> | 2<sup>0</sup> | _Total_ |
| --------------|-----:|----|----|----|---|
| **bit-value**         | **_1_** | 0 | 0  | **1**  | |
| **2<sup>x</sup> x bit-val =** | **-8** | 0 | 0 | **1** | **_= -7<sub>10</sub>_** |

This way of calculating the decimal value might be a little easier when working with smaller decimal numbers, but then becomes a little more complicated to do some mental math when you're working with bigger decimal numbers: 

| 2<sup>x</sup> | (-/+)2<sup>7</sup> | 2<sup>6</sup> | 2<sup>5</sup> | 2<sup>4</sup> | 2<sup>3</sup> | 2<sup>2</sup> | 2<sup>1</sup> | 2<sup>0</sup> | _Total_ |
| --------------|-----:|----|----|----|----|----|----|----|---|
| **bit-value**         | **_1_** | **1** | **1**  | **1** | 0 | 0 | **1** | 0 | |
| **2<sup>x</sup> x bit-val =** | **-128** | **64** | **32** | **16** | 0 | 0 | **2** | **1** | **_= -14<sub>10</sub>_** |

Thankfully, there aren't a lot of situations I can think of where you'd have to interpret between the two without a calculator handy!




## Finding the max and min with signed binary numbers

The range of positive decimal numbers that can be stored in any sized bit integer is shortened by the fact that the first bit is used to denote sign. This means that, in the case of a 32-bit signed integer, we are actually working with 31 value bits instead of 32, and that last bit could have stored an _exponentially_ bigger integer. In fact, this completely _halves_ the range of positive integers we can work with compared to a 32-bit unsigned integer. That one extra bit would have doubled our max possible integer, and without it, we lose the ability to store as many positive integers. 

On the other hand, we gain the ability to store a bunch of negative integers that we couldn't have before with an unsigned bit integer. In the end, the size of the range we work with is kept the same, but the range moves to account for being able to store both positive _and_ negative numbers.

Let's look at a 4-bit unsigned vs signed integer. Our range might move, but the _amount_ of integers that can be stored don't actually change. 

![Mapping Signed and Unsigned bit integers](https://scs.hosted.panopto.com/Panopto/Pages/Viewer/Thumb.aspx?eventTargetPID=f02fb73c-8769-43de-a970-bda301209a04&sessionPID=57b29532-2a7d-4dac-8168-8892127d9e49&number=20&isPrimary=false&absoluteTime=13076614406.5337)



Because of this loss of a bit, our maximum is calculated by **2<sup>bits - 1</sup> - 1**, or, if working with 32-bit integers **2<sup>31</sup> - 1**.
I explained why we have to subtract the one [last time](https://dev.to/aidiri/x-bit-integers-solving-with-a-range-3gm3), which we still have to do since we're including the zero in the range and not subtracting would cause one extra bit to be needed to store that number.

Our minimum in the range is the inverse, **-2<sup>bits - 1</sup>**, or, if working with 32-bit integers, **-2<sup>31</sup>**. We don't subtract one for our minimum range because the zero is not included and we start counting from -1. This gives us that one extra negative number in our range that can be represented. 

Seeing the range above might help visualize why there isn't a subtraction from the lower range while there is for the upper range. Zero is included in the green range, but not in the red range of signed bits. We start at -1 and can have the same amount of numbers represented as non-negatives. 


|  	|  	|  	|  	| 	|  	|  	|  	| *	| *	| *	| *	| *	| *	| *	| *	|
|:--:	|:--:	|:--:	|:--:	|:--:	|:--:	|:--:	|:--:	|:-:	|:-:	|:-:	|:-:	|:-:	|:-:	|:-:	|:-:	|
| -8 	| -7 	| -6 	| -5 	| -4 	| -3 	| -2 	| -1 	| 0 	| 1 	| 2 	| 3 	| 4 	| 5 	| 6 	| 7 	|
_Here we have 8 positive integers._

|  	|  	|  	|  	| * | *	| *	| * | *	| *	| *	| *	| 	| 	| 	| 	|
|:--:	|:--:	|:--:	|:--:	|:--:	|:--:	|:--:	|:--:	|:-:	|:-:	|:-:	|:-:	|:-:	|:-:	|:-:	|:-:	|
| -8 	| -7 	| -6 	| -5 	| -4 	| -3 	| -2 	| -1 	| 0 	| 1 	| 2 	| 3 	| 4 	| 5 	| 6 	| 7 	|
_Here we have 8 positive **and** negative integers. But still only 8 total integers._

### The problem


Going back to the problem solved in the last post, this time the solution will involve creating a restricted range for a _signed_ integer.

> **Given a 32-bit signed integer, reverse digits of an integer.**

We know this is a 32-bit integer with 32 zeroes and ones, the very first of which is denoting the sign.
Working with 31 bits that could represent the value of the number, the biggest positive binary integer we could have would be 31 ones after the first, sign bit of zero, which gives us a positive sign.

This means the largest decimal number we could deal with would be **2<sup>31</sup> - 1**, or **2,147,483,647**

The largest negative binary integer (and by largest I mean smallest?) would be 31 zeroes with the sign bit being a one, telling us it's negative.

This means the smallest decimal number we could deal with would be **-2<sup>31</sup>** or **-2,147,483,648**


### The solution

```javascript
const reverseInteger = (x) => {
    let reversed = "";
    strx = x.toString();
    for(let num of strx){
        reversed = num + reversed
    }
    reversed = parseInt(reversed, 10);
    if(x<0){
        reversed = reversed * -1;
    }
    //Setting the range!
    if (reversed > Math.pow(2, 31) - 1 || reversed < Math.pow(-2, 31)) return 0;

    return reversed;
};
```

The problem is essentially asking to make sure we don't return a number that can't be stored as a 32-bit signed integer. Here we're skipping how to actually solve this problem and focusing on the range since I've walked through the solution [previously](***).


The line right before the `return` checks whether the end integer contained in `reversed` is within range. If `reversed` is greater than **2<sup>31</sup> - 1** OR less than **-2<sup>31</sup>**, it returns 0.

If this were an unsigned 32-bit integer, there would've been a range from 0 to 2<sup>32</sup>-1, or 4,294,967,295. That upper range is twice the range of 2<sup>31</sup>. You can think of that missing "half" of the range that would have stored those positive numbers as being used to store your negative numbers instead. Same-sized range, just different start and endpoints in that range. 

***
### Fin!

That finishes my series on binary numbers for the average non-computer science degree holders! 

This was a really fun (and frustrating) learning process. I fully expect there to be holes in my overview as there's just way too much to cover without going unnecessarily in-depth.

I want this to be a good jumping-off point for those who want to know the basics so if there's anything that wasn't clear (or I assumed you knew something that you didn't), let me know!

Happy Coding!

***

Resources:

[Reverse Integer LeetCode Problem](https://leetcode.com/problems/reverse-integer/)
[Signed Binary Numbers](https://www.electronics-tutorials.ws/binary/signed-binary-numbers.html)
[Decimal to Binary Converter](https://www.rapidtables.com/convert/number/decimal-to-binary.html)
[Signed Numbers - Watson](http://watson.latech.edu/WatsonRebootTest/ch11s4p1d.html)
[Rounding Algorithms 101 Redux - EETimes](https://www.eetimes.com/rounding-algorithms-101-redux/)
[Bits, Bytes, and Integers - Carnegie Mellon](http://www.cs.cmu.edu/afs/cs/academic/class/15213-s12/www/lectures/02-03-bits-ints-1up.pdf)