# Numbers and Numeric Types in Swift

I'm currently working my way through the Swift language guide. Recently, I read the section about numbers and numeric types. Most of the stuff in this chapter should be familiar to developers who have been working in statically typed languages before. Some of the decisions of the language designers, though, are quite interesting and useful in my opinion. Here's what I found.

## Numeric Types

Swift currently supports ten numeric types. There are four types for signed integer types of different bit sizes and their unsigned equivalents, prefixed with `U`

:

`Int8`

and`UInt8`

`Int16`

and`UInt16`

`Int32`

and`UInt32`

`Int64`

and`UInt64`

There's also an additional type named `Int`

which has the current platform's native word size. It corresponds to `Int32`

on a 32-bit platform and to `Int64`

on a 64-bit platform.

Finally, Swift offers two floating-point types which differ in size and in precision of their fractional component:

`Float`

(size: 32-bit, precision: ≥6 decimal digits)`Double`

(size: 64-bit, precision: ≥15 decimal digits)

## Numeric Literals

Integer Literals can be written in one of several representations:

**decimal**, no prefix**binary**, prefixed with`0b`

**octal**, prefixed with`0o`

**hexadecimal**, prefixed with`0x`

The underlying value of the literal is independent of its representation. Therefore, the following four literals all have the same value:

`let decimal = 42 // 42 = 4 * 10 + 2 * 1`

let binary = 0b101010 // 42 = 1 * 32 + 1 * 8 + 1 * 2

let octal = 0o52 // 42 = 5 * 8 + 2 * 1

let hexadecimal = 0x2A // 42 = 2 * 16 + 10 * 1

Floating-point literals can only be decimal or hexadecimal. In comparison to many other programming languages, digits are **required on both sides** of the decimal point, thus making `.5`

an invalid literal (which should've been written as `0.5`

instead). In Swift, it's all about explicitness.

## Formatting Numeric Literals

Swift allows you to insert arbitrary underscores in your numeric literals to improve the readability of long numbers by grouping digits together. You could initialize an integer constant holding the earth's population like this:

`let earthPopulation = 7_100_000_000`

The underscores are purely syntactic sugar and don't change the underlying value of the literal in any way.

## Scientific Notation

Not surprisingly, numeric literals can be denoted using the scientific `e`

notation for decimal floats. You could write `7100000000`

as `7.1e9`

, meaning *7.1 times 10 to the 9th power*.

There's also a notation for hexadecimal floats which uses the `p`

notation. The base is 2, not 10, so `0xAp3`

means *10 times 2 to the 3rd power*, which equals 80. Honestly, I've never come across that notation in my entire history of programming and I'd be careful to use it because it might lead to a lot of confusion. (It makes for great Star Wars anecdotes like `0xC3p0`

, though.)

## The Remainder Operator

Similar to other C-like languages, Swift supports the `%`

operator to calculate the **remainder** of a division. This operator is often referred to as *modulo*, which, strictly speaking, is incorrect in the mathematical sense. The value of `-5 mod 3`

is `1`

, while Swift (and many other languages) return `-2`

because `-5 = (-1) * 3 - 2`

.

Another aspect that sets Swift apart is that its remainder operator also works on floating-point numbers **on both operands**:

`let remainder = 2.5 % 1.1`

// 0.3

The sign of the second operand never changes the value of the expression.

## Numeric Type Conversions

In Swift, conversions between different numeric types have to be made explicit. The following addition is therefore not valid Swift code:

`let one = 1`

let oneHalf = 0.5

// Doesn't work:

let oneAndAHalf = one + oneHalf

You can solve this problem by initializing a new `Double`

from an existing `Int`

:

`let oneAndAHalf = Double(one) + oneHalf`

I think it's helpful to be clear about the (otherwise implicit) conversion that needs to happen when performing an addition on differently typed operands. This is another point where the Swift language designers favored clarity over brevity:

Because each numeric type can store a different range of values, you must opt in to numeric type conversion on a case-by-case basis. This opt-in approach prevents hidden conversion errors and helps make type conversion intentions explicit in your code.

## Explicit Overflows

To avoid errors caused by accidental overflow of numeric types, Swift doesn't allow values to overflow by default. Trying to perform such an invalid operation results in a runtime exception – *fail hard, fail early*. Examples of invalid operations include adding 1 to the maximum integer value or assigning a negative number to an unsigned variable.

If, for some reason, you do need arithmetic operations to deal with overflowing values, Swift provides five so-called *overflow operators*, all of which are prefixed with an ampersand sign:

- overflow addition:
`&+`

- overflow subtraction:
`&-`

- overflow multiplication:
`&*`

The following two operators once existed, but were **removed in Swift 1.2**:

- overflow division:
`&/`

- overflow remainder:
`&%`

You'll find all of the nitty-gritty details about value overflow in the language guide under *Advanced Operators // Overflow Operators // Value Overflow*.