As you may know, Swift is a type-safe language and good understanding of the data types that are available is therefore critically important. In this post, we’re going to start looking at these in detail with a look at the numeric data types available in Swit.

## Integers

Integers represent whole numbers, numbers that have no fractional components like `0`

, `42`

or `-128`

.

### Signed and Unsigned Integers

In Swift, the integers are primarily divided into two groups. They can either be *signed* (which include negative values, zero and positive values) or *unsigned* (which covers only zero and positive values).

### Sized Integers

In addition to being either signed or unsigned, in Swift each of these two groups also come in four different sizes; 8, 16, 32 and 64-bits versions.

In Swift, the names of the integer data types follow the same general scheme as is used in languages like C and as with all types in Swift, they always start with a capital letter.

For the unsigned types this initial capital letter is the letter `U`

(to indicate that they are *unsigned*). This is then followed by the word `Int`

(with a capital `I`

) to indicate that they are also part of the integer type family. In the case of the signed integer types the initial letter `U`

is omitted and they simply start with the word `Int`

. After the word `Int`

though, both the signed and unsigned integer types include a number to indicate how many bits of storage the particular type makes use of. This can be one of the aforementioned 8, 16, 32 or 64 to represent 8, 16, 32 or 64-bits respectively.

Putting all of this together then you can see that we have a whole range of integer types at our disposal. These include integer types such as `UInt8`

(an unsigned integer type using 8 bits of storage), `Int16`

(a signed integer, – notice it has no leading `U`

– using 16 bits of storage) or `UInt64`

(an unsigned integer type using 64-bits of storage). The full list is below:

- Int8
- Int16
- Int32
- Int64
- UInt8
- UInt16
- UInt32
- UInt64

Now although these types are useful, there are a lot of times when we don’t actually care about the number of bits of storage our integers are using. For these situations we make use of another, more generic, integer type built into Swift called `Int`

.

### Int

The `Int`

type is the generic integer type of choice when writing Swift code and you should use it whenever possible. By using `Int`

consistently instead of the sized integer types we just looked at we can increase both the portability and readability of our code and can significantly reduce the need to convert between different data types.

Given it’s more generic nature, you may be wondering how much storage the `Int`

type actually uses to store its values and this is actually a good question. Under the hood the `Int`

type maps to *“a type that is of the same size as the current platforms native word size, the smallest addressable unit of memory on the particular platform.”*

Now that may be a bit of a mouthful but all it really means is that on a 64-bit platform the `Int`

type would be the equivalent size to an `Int64`

and on a 32-bit platform, it would be equivalent to an `Int32`

.

With the `Int`

type therefore using at least 32-bits of storage, for most situations the type provides more than enough storage space for the integer values you’ll normally be working. If however, you have specific requirements such as working with data from external data sources, are worried about performance or memory usage or are trying to perform other optimisations, you have the option of falling back to one of the sized integers such as `UInt8`

, `UInt64`

etc.

In addition to the `Int`

type though, Swift also contains an unsigned equivalent called `UInt`

.

### UInt

In similar fashion to the `Int`

type, the `UInt`

also maps to the native word size on a given platform so on a 64-bit platform it is the same size as a `UInt64`

and on a 32-bit platform it is the same size as a `UInt32`

.

Despite the fact that the `UInt`

type is available within Swift though, Apple recommends that where possible, you use `Int`

in preference to the `UInt`

, even if the values that you are storing are unsigned.

Now, at first, this may seem strange, after all, why use a signed type even when you know the values you’re going to be storing are unsigned? But remember what I said about being consistent. By always using a single integer type whenever possible, we make our code easier to read, easier to move between platforms and also make sure that the values in our constants and variables are immediately interoperable without the need for any sort of conversion. It also has the advantage that we can take make use of the inbuilt type inference mechanism built into Swift which infers integers to be of type `Int`

by default.

## Floating-Point Types

So, we’ve looked at the integer types, lets now take a look at their counterparts, the *floating-point* numbers.

Floating-point numbers are numbers that have a fractional component such as `3.14159`

or `101.123`

and as such are usually written using a decimal point.

Due to the way they are stored, variables and constants that are defined as floating-point numbers can store a much wider range of values than integers using the same number of bits of storage including values that are not only smaller, but also much larger than integers of the equivalent size. They do this though by lose some level of precision.

For the most part this loss of precision is not a major problem, especially when you stack this up against the greater flexibility that these numbers provide but you need to be aware that in the case of floating point numbers it can lead to some strange results such as when trying to test two floating point values for equality or trying to store a values that cannot be represented exactly using binary.

### Float and Double

In Swift, there are two types of floating-point number, both of which are signed. These are the `Float`

type which represents 32-bit floating point numbers with at least 6 decimal digits of precision and the`Double`

type which represents 64-bit floating point numbers at least 15 decimal digits of precision.

In similar fashion to the discussion we had about `Int`

and `UInt`

, in the interests of consistency, Apple recommend that we use the `Double`

type in preference to the `Float`

type in situations where both types are equally applicable.

Their reasoning is the same as we saw above (mainly readability, consistency and portability) and also ties into Swifts type inference mechanism, which in the case of floating-point numbers, infers values to be of type `Double`

by default.

## Numeric Literal Values

So, we’ve looked at the two groups of numeric data types in Swift, the integer types and the floating-point types but how do we actually write values of these types in our code? This is where *literal values* come in.

Literals values are exactly as they sound, they are values that are *literally* written in our code verbatim and in Swift we have a number of options for how we can write them. Let’s look at writing integer literals first.

### Integer Literals

In the case of the integer values, the first form we can use to write integer values in is good old *decimal*.

Decimal is the form you’ll be most familiar with where values are represented in a base-10 format without any sort of prefix or extra notation. For example:

```
let decimalInteger = 42
// 42 = (4 * 10) + (2 * 1)
```

On top of decimal notation though, there are three other notations that we can use to write integer values in Swift; binary, octal and hexadecimal. Let’s look at each of them in turn.

#### Binary Integer Literals

When we write an integer value in binary notation in Swift, we’re representing the value in a base-2 notation and write it with a leading zero, followed by a lowercase `b`

(for binary) followed by the value written in base-2.

For example, if I wanted to initialise a constant with the decimal value 42 written in binary notation I would write:

```
let binaryInteger = 0b101010 // The equivalent of decimal 42.
// 42 = (1 * 32) + (1 * 8) + (1 * 2)
```

#### Octal Integer Literals

The next option we have is octal notation. Octal notation represents values in a base-8 notation and to indicate the values is in octal notation we write a leading zero followed by a lowercase `o`

(for octal) followed by the value in base-8.

For example, if we wanted to initialise a constant with the octal equivalent of decimal 42 we would write:

```
let octalInteger = 0o52 // The equivalent of decimal 42.
// 42 = (5 * 8) + (2 * 1)
```

#### Hexadecimal Integer Literals

The final choice we have is hexadecimal notation. When we write a literal value in hexadecimal form we prefix the value with a zero followed by a lowercase `x`

(the `x`

from hexadecimal) followed by the number in hexadecimal.

So if we wanted to declare a final constant, again with the equivalent of the decimal value 42, but this time written in hexadecimal we would write :

```
let hexadecimalInteger = 0x2A // The equivalent of decimal 42.
// 42 = (2 * 16) + (10 * 1)
```

### Floating-Point Literals

As with integer values, it is relatively common to write floating-point literals within our code and in the case of floating-point numbers we actually have slightly fewer choices when it comes to formats as we are limited to either decimal notation or hexadecimal notation.

#### Decimal Floating-Point Literals

The first notation, *decimal*, is the one you be most familiar with. As you know this format uses a decimal point to separate the integer part of the number from the fractional part. For example:

`let decimalDouble = 3.14159 // Pi`

One thing to note is that in Swift, you must *always* have a number on both sides of the decimal point so writing something like `.5`

in Swift is invalid.

#### Hexadecimal Floating-Point Literals

In addition to decimal notation, we can also write floating point numbers in Swift using hexadecimal notation. To write floating point numbers in hexadecimal notation you prefix the number with a zero, followed by a lower-case `x`

(`0x`

). When writing floating-point numbers in this way, both the whole number and fractional parts are both written in hexadecimal and are separated by a decimal point. For example, I could write `pi`

in the following format:

`let hexadecimalDouble = 0x3.374F`

## Scientific Notation

Now, if you can remember back to school, when you were writing either very larger or very small numbers you may have used something called *scientific notation*.

Scientific notation is a kind of short hand, a more convenient way of writing floating point numbers using an optional *exponent* and given that I’ve mentioned it here, it won’t surprise you that we also have the option of using this notation in Swift.

To write decimal floating point literals in scientific notation we use an upper or lowercase letter `e`

to separate the base value from the exponent. The total value of the floating point number is then equivalent of multiplying the base value, (the part of the number before the `e`

), by 10 (in the case of decimal values) raised to the power of the exponent value (where the exponent value is the part of the number after the `e`

).

So if I wrote, the following: `2.56e2`

it would be the equivalent of writing `2.56 * 10^2`

or `256`

.

Similarly, if I wrote: `2.56e-2`

, (notice here that I used a negative exponent), it would be the equivalent of writing: `2.56 * 10^-2`

or `0.0256`

.

In Swift, we can also write floating point numbers in hexadecimal format and still make use of scientific notation.

When writing in hexadecimal format, instead of using an `e`

or `E`

to separate the base value from the exponent we , we use an upper or lowercase letter `p`

. When written in hexadecimal format, the literal value is equivalent to multiplying the base value (which is written in hexadecimal) by 2 raised to the power of the exponent (which is also written in hexadecimal).

So for example if we wrote the following floating point literal: `0xAp2`

It would be the equivalent of writing: `10 * 2^2`

or `40.0`

. Notice how the number is still prefixed with the `0x`

to indicate that is is a hexadecimal number.

Similarly if I wrote`0xAp-2`

It would be the equivalent of writing: `10 * 2^-2`

or `2.5`

.

### Formatting for Numeric Literal Values

In addition to the different syntaxes that we can use to write numeric literal values, Swift also allows us to some syntactic sugar that helps us make those values easier to read. Firstly, both integers and floating point numbers can be written with additional leading zeros e.g.:

`let pi = 00003.14159`

They an also be written with underscores between group of digits to help with readability:

```
let largeInteger = 3_000_000_000
let largeDouble = 2_345_678.910_111_213
```

In both cases, the additional syntactic sugar has no effect on the underlying value that is represented, it is simply ignored by the compiler.

## Integer Value Limits

Now, as I mentioned earlier, integer types in Swift use a fixed number of bits in which to store their values. In doing so, the number of bits they use, provides a direct limit on the range of values that variables or constants of that type can store.

For example, the `Int8`

type, a signed integer using 8 bits of storage can store values ranging from `-128`

to `127`

whereas it’s unsigned equivalent (`UInt8`

) can store values that range from `0`

through to `255`

.

In both cases, if you attempt to store a value that does not fit within the range of values supported by the type, the compiler will indicate it as an error at the point you compile your code.

So given the fact that the integer values in Swift have a particular range of values that they can store, how do we find out how do we find out what this range of values is without doing some fancy binary maths?

Well, in Swift, built into each of the integer types are a couple of type properties that allow us to discover this information.

## Value Ranges of Types

To find the smallest value a particular integer type can store we use the `min`

property and access it using *dot notation*.

Note: All the *dot notation* is, is using a dot or full stop to separate a item we want to know something about (in this case a type) from the information we want to know about it (in this case the minimum value it can store which is represented by the `min`

property).

For example if I wanted to access the minimum value that can be stored in say an `Int8`

I would write:

`Int8.min // Returns -127`

We can also access the maximum value that can be stored in a particular type. You can do this using the `max`

property. For example:

`Int8.max // Returns 128`

In both these cases, the values returned from these properties are of the same type as the type whose properties we’ve accessed so in the examples above the values returned from the `min`

and `max`

properties would both be of type `Int8`

. This allows us to easily use these returned values in calculations of that type without the need to convert them. With that said, though, the need to convert values between different types is not unusual in Swift, so we’ll take a look at that next.

## Numeric Type Conversion

### Converting Between Integer Types

As we saw just now, each of the integer value types in Swift have a different range of values that they can store and to convert a value from one data type to another Swift forces us to explicitly opt-in to the conversion on a case-by-case basis. By doing so, it helps avoid hidden conversion errors by making us indicate these conversions explicitly.

The mechanism for converting one type to another in Swift is simple. We simply create a new value of the desired type and initialise it with the existing value:

```
let daysInAYear : Int16 = 365
let daysInJanuary : Int8 = 31
let totalDays = daysInAYear + UInt16(daysInJanuary)
```

In this example, we initially create two constants, the first, `daysInAYear`

is of type `Int16`

and the second, the `daysInJanuary`

is of type `UInt8`

. In the last line, we then create a new constant (`totalDays`

) by combining the values held in the two previous constants. To do this though, the values that we are combining have to be of the same time so we first have to convert the `daysInJanuary`

constant into an `Int16`

to match the type of the `daysInAYear`

constant. To do this we create a new value of type `UInt16`

using initialisation syntax passing in the value from the `daysInJanuary`

constant. When then combine the new value with the “daysInAYear`constant to create the`

totalDays`constant which Swift infers to be of type`

Int16`.

### Integer Initialisers

The `typeName(initialValue)`

we used in the example above is an example of using the default `UInt16`

initializer and as you can see, we provided it with an initialisation value as part of that call (in this case the value held in the `daysInJanuary`

constant). Behind the scenes, the `UInt16`

type has a number of different initialisers, each of which accepts an initialisation parameter of a different type. In this case we make use of the initialiser that accepts a `UInt8`

parameter but there are others. It’s a similar story with the other numeric types in Swift. Each them has a specific set of initialisers, each tailored to accept initialisation parameters of specific types. This means that you can’t simply initialise numeric values with any old type. There are also some subtleties to these initialisations as well. For example, the `UInt8`

type has an initialiser that accepts a `UInt16`

parameter but if the value you provide doesn’t fit within the range of values supported by a `UInt8`

(`0`

to `255`

), the compiler will, by default, give you an error.

```
let littleUInt16 = 120
let littleUInt8 : UInt8 = UInt8(littleUInt16)
let bigUInt16 = 1440
let bitUInt8 : UInt8 = UInt8(bigUInt16) // Compiler error.
```

### Converting Between Integer and Floating Point Types

In addition to being able to convert between different integer types, Swift also allows us to convert between integer and floating-point types as well. As with the integer types, any conversion must be explicitly stated though:

```
let startingRatio = 1 // Inferred as an Int
let frationalRatio = 0.61803398875 // Inferred as a Double
let goldenRatio = Double(startingRatio) + fractionalRatio
// goldenRatio equals 1.61803398875 and is inferred to be of type Double.
```

As we saw with the integer example earlier, in order to be able to combine the two values, we must first ensure that they are all of the same type. To achieve this, we create a new `Double`

value using the value stored in the `startingRatio`

constant (in this case, we’re calling an initialiser on the `Double`

type that accepts an `Int`

as a parameter) and then add that to the existing `fractionalRatio`

constant. The result is the `goldenRatio`

constant and which is inferred to be of type `Double`

by Swift.

### Converting Between Floating Point and Integer Types

In addition to being able to convert from integers to floating point numbers, we can also convert the other way, from floating point number to integers and as we’ve seen with all the conversions so far, we must explicitly opt-in to this. In the case of floating point to integer conversions, this is even more important than normal as when a floating point value is converted into an integer value in Swift, the fractional part of the floating point number is truncated:

```
let integerGoldenRatio = Int(goldenRatio)
// integerGoldenRatio is equal to 1 and is inferred to be of type Int
```

This applies for both `Float`

and `Double`

values.

### Converting Numeric Literals

One thing to point out at this point is are the rules for converting numeric literals. When we include numeric literals in our code they aren’t actually typed until they are evaluated by the compiler. This means that any literal values you write in your code don’t have to be converted before they can be combined. For example, if we revisited our golden ratio example notice how in this example, we don’t need to convert the integer literal `1`

before we combine it:

`let otherGoldenRatio = 1 + fractionalRatio`

## Wrapping Up

So that about wraps it up for the numeric data types in Swift. As ever, if I’ve missed anything or you have an questions, get in touch.