How and Why To Use Unsigned Integers (UInt)

In the beginning there was the unsigned integer, and it was good. If you go deep into machine code you will still find that any device is nothing more than unsigned integers. All other values Int, Float, Bool, Character, and String are forms or collections of unsigned integers. To a modern high-level language like Swift, we don’t think about this much. However there are times unsigned integers become important.

The Difference Between an Unsigned and Signed Integer.

Before we begin, Here’s a little background for those not familiar with some core concepts in computer science. We normally measure data storage units in bytes. Each byte is represented by a binary number comprised of bits. Depending on the processor in a computer the number of bits is different. For example, an Apple ][+ was an 8-bit byte. iPhones up to the iPhone 5 are 32 bit bytes, from the iPhone 5 on, iPhones were 64 bit bytes.

Since a bit can be either on of off, we have two states. Computer scientists realized that a series of bits could add up by power of two. A four bit number for example could represent the sixteen numbers 0 – 15, An eight bit number could represent the numbers 0-255 , Thirty two bit numbers could have values of 0 to 4,294,967,295. Sixty four bit bytes can have values of 0 to some number so big we really don’t have to think about it (1.844 x 10^19 approximately).

Each bit becomes a power of two – it’s a digit of a binary number. For example, the four bit number 1010 becomes

1 * 8 = 8
0 * 4 = 0
1 * 2 = 2
0 * 1 = 0

Adding the bits together, 8 + 2 = 10. The four-bit binary number 1111 is 15 and the four-bit binary number 0000 is 0. To prevent the binary number getting confused with decimal numbers, the prefix 0b is often used in code and documentation to describe a binary number. 0b1011 is 11 decimal for example.

But these numbers are only positive integers. Subtract 1 from zero, and the program crashes with an exception. For many calculations, we need negative numbers. Computer science came up with a brilliant solution which we call signed integers. Take the first bit of a byte and make it a positive or negative sign. If zero, the value is positive. If one the value is negative. This cuts the number of positive values in half, but adds negative values. Using a four bit example, 0b0101 as a signed integer is 5. However, for reasons I won’t get into here, they did one thing that wasn’t intuitive: negative numbers count down from their maximum value. For example 0b1101 as a signed integer is 0b111 – 0b101 which is -2 not -5 as you’d think intuitively.

Introducing the Flavors of UInt

Since we use number with positive and negative integers more often than positive integers only, the type Int is the signed integers. If we want a value without a sign, then we use the type UInt. UInt creates a integer of the same bit size as the device’s processor can handle. There is only one reason you need a UInt: when you need some really big integers. But since the maximum integer changes depending on device this is not a great idea.

Where unsigned integers find their use is with a specified number of bits. Swift provides the types UInt8,UInt16, UInt32, UInt64, which are for 8, 16, 32, and 64 bit numbers. Why do we need these? Because most uses of unsigned integers will specify the number of bits used.

Unsigned integers are pure 1’s and 0’s, and we can use them in several ways. We can make each bit represent the state of something else. This is common in device control. You may use several bits of a byte to turn on or off different parts of the device. Another use is to limit values between two numbers. Many devices, no matter how sophisticated they are, still use traditional eight, sixteen, or thirty two bit values. The standard for RGB color on the web and many non-Apple API’s is a collection of three eight bit (0-255) numbers, one each for red,green, and blue.

Basic Math With Unsigned Integers

Math functions work the same as Int, with one exception: you have boundaries to watch for. All of these will work with no problems:

let c:UInt8 = 0b00000101
let d:UInt8 = 128   //0b10000000
let e:UInt8 = 255   //0b11111111
let f:UInt8 = 10    //0b00001010

print("Math operators")
print(d + 1 )      // 129
print(d - 1 )      // 127
print(f * 2)       // 20
print(d / 3)       // 42

However, this will return an exception

print(f - 11)

as will this:

print(e + 1)

Both exceed the boundaries of 0-255.

Overflow Math

You might want to cross those boundaries. In those cases we want the value to wrap around to the the other end. For an UInt8 for example, we want 255+1 to be 0 and 0 – 1 to be 255. We use the overflow math operators &+ and &-

print(f &- 11)
print(e &+ 1)

Bit Shift Operators

Math operators in unsigned integers are of secondary importance to bitwise operators. We use unsigned integers most often to control individual bits. There are two types of operations: logical operations and shifts.

Shifting moves one bit from its current position to another position We use the operators << and >> to shift. We specify after the operator how many bits we want to move. To move one bit to the right we would use this:

print(f <<t; 1) //0b00000101 = 5

one bit to the left, we would use this:

print(f >> 1) //0b00010100 = 20

A bit shift replaces the empty space of the shift with a zero. Thus 255 (0b11111111) shifted twice places two 0’s at the beginning or end of the value, and dumps two 1’s.

print(e >> 2) //0b00111111 = 63

Signed integers make a mess out of bit shifts because of the negative number representation. For that reason, avoid them and use unsigned integers if you need to make a bit shift.

Logical Operators

We can also perform logical operations on bits. We can use AND(&) , OR(|), and NOT(~) operators for unsigned integers.

print("logical operators")
print(~f)  //NOT(0b00001010) = 0b11110101 = 245
print(d & e) //0b10000000 AND 0b11111111 = 0b10000000 = 128
print(d | e) //0b10000000 OR 0b11111111 = 0b11111111 = 255

The expression d > e did not change anything. As bitwise operations work on a bit-to bit comparison, only the leftmost bit was 1 since both were 1. We can use this to make a bit mask, a way filtering bit data to get what we want.

For example, let’s suppose we have a Bluetooth connection to an Arduino controller. The controller transmits back to our application data about ports 0 through 7, which are connected to a set of digital sensors. We want to know when a sensor is on, represented as a 1 for its bit. Since any bit that is 1 creates a non-zero value, check if the value transmitted is non-zero. We could write a function like this:

func isSensorOn(sensors:UInt8) -> Bool{
    return sensors != 0
}

However there’s a problem. Pins 0 and 1 are receive and transmit for serial data. They will likely be chattering nonstop with data, messing up our function. We need to filter out pins 0 and 1. We can make a bit mask that says “only give me data for pins 2 through 7” like this:

func isSensorOn(sensors:UInt8) -> Bool{
    let bitMask:UInt8 = 0b11111100
    return (sensors & bitMask) != 0
}

What if I wanted to get a specific sensor’s reading as a Bool? I could make a bit mask using a shift

func isSensorOnPin(pin:UInt8, sensors:UInt8) -> Bool{
    let bitMask:UInt8 = 1 << pin //shift to the correct pin
     return (sensors & bitMask) != 0
}

It is bit masks which will be the biggest use of unsigned integers you will have. When you are working directly with bytes, they provide a way to examine or change individual bits. Apple’s API’s often don’t require them and does a good job or hiding them in constants, classes and methods. For example, Apple uses a CGFLoat of 0 to 1.0 instead of 0 to 255 for color values using UIColor(red:green:blue:alpha). You will find exceptions, and indeed a few places where bit masks are required. Raw image data, device communications and the like will often need bit masks to work properly. While the beginning developer might not need unsigned integers and bit masks, more advanced developers working with image data directly and communicating with outside devices will find them very useful.

The Whole Code

I’ve posted this code on the IBM Swift Sandbox if you want to play with it. You can find it here. I suggest cuttng and pasting the code there and not here as WordPress has a terrible habit of mangling the code.

//  TODO: Write some awesome Swift code, or import libraries like "Foundation",
//  "Dispatch", or "Glibc"
// find this code at the IBM Sandbox at http://swiftlang.ng.bluemix.net/#/repl/15f819c02e0b09f3d01ef07292bee43d06ee0774ff0261655f3b01f159cfac83

// representing numbers in different bases -- not covered in lesson 
let i:Int = 320  //decimal
print(i)

let b:Int = 0b1111 //binary
print(b)

let h:Int = 0xff //hex
print(h)

let o:Int = 0o77 //octal
print(o)

//declaring an Unsigned Integer. You must declare the type for this. 
let a:UInt = 26 
print(a)

//using operators 
let c:UInt8 = 0b00000101
let d:UInt8 = 128   //0b10000000
let e:UInt8 = 255   //0b11111111
let f:UInt8 = 10    //0b00001010

print("Math operators")
print(d + 1 )      // 129
print(d - 1 )      // 127
print(f * 2)       // 20
print(d / 3)       // 42
print("Overflow Math operators")
print(f &- e)     // 11
print(e &+ 2)     // 1

print("Bit shift operators")
print(f >> 1) //0b00000101 = 5
print(f << 1) //0b00010100 = 20
print(e <> 2) //0b00111111 = 63



print("Logical operators")
print(~f)  //NOT(0b00001010) = 0b11110101 = 245
print(d & e) //0b10000000 AND 0b11111111 = 0b10000000 = 128
print(d | e) //0b10000000 OR 0b11111111 = 0b11111111 = 256

print("Using bitmasks to get a bit")
func isSensorOn(sensors:UInt8) -> Bool{
    let bitMask:UInt8 = 0b11111100
    return (sensors & bitMask) != 0
}

print(isSensorOn(10))  //true
print(isSensorOn(11))  //true
print(isSensorOn(3))  //false
print(isSensorOn(0))  //false

func isSensorOnPin(pin:UInt8, sensors:UInt8)->Bool{
    let bitMask:UInt8 = 1 << pin //shift to the correct pin
     return (sensors & bitMask) != 0
}
print("Check individual pins")
print(isSensorOnPin(3, sensors:10)) //true
print(isSensorOnPin(3, sensors:11)) //true
print(isSensorOnPin(4, sensors:11)) //false
print(isSensorOnPin(5,sensors:255)) //true
print(isSensorOnPin(4,sensors:0))  //false

10 Replies to “How and Why To Use Unsigned Integers (UInt)”

  1. Hi,
    Nice article. A few remarks:
    – you don’t explain what 0b means at the beginning of your bit wise representation
    – print(e 2) isn’t explained, it should be either e <> 2 in that paragraph over bit shifting
    – quote: “Unsigned integers make a mess out of bit shifts. For that reason avoid them and use unsigned integers if you need to make a bit shift.” You mean ‘signed integers make a mess’?
    – your first declaration of isSensorOn in the text is wrong, bitMask != 0 doesn’t make sense if you don’t declare bitMask first.
    – quote: “Much of graphic systems use unsigned interest for, Apple uses CGFloat” this sentence needs some rework :)
    – print( d | e) will return 255 not 256 :)

      1. This have been an ongoing problem for about a month. WordPress messes up the > , &, <, and " characters. Even in a <pre> when it’s supposed to ignore them replaces them with the HTML codes. Slows down production big time.

  2. Nice post, but
    “Unsigned integers make a mess out of bit shifts because of the negative number representation.” should probably read
    “_Signed_ integers make a mess […]”

    1. yep you are right. Fixed. Hopfully it didnt introduce any more errors. WordPress has been very stupid lately with the &, , and ” characters, changing them whenever I put them in to HTML garbage, even if they explictly shouldn’t.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s