# Working with very large numbers in Swift — BigInt

Numbers are fundamental to every programming language in existence. Depending on the systems architecture that you’re programming for, there are restrictions the size of the numbers it can support.

Numbers are fundamental to every programming language in existence. Depending on the systems architecture that you’re programming for, there are restrictions the size of the numbers it can support.

Engineers writing code for an 8-bit system such as the NES, only had access to integers between -128 to 127 (signed). However with some tricks, such as breaking the numbers into smaller pieces, any cpu is capable of working with numbers of any size.

This method of breaking the numbers up can be performed at the hardware level, but there are some software tricks we can use too.

The following table describes some common available integer sizes.

```
╔═══════╦═════════════════════════════════════════════════════════╗
║ Type ║ Output Range ║
╠═══════╬═════════════════════════════════════════════════════════╣
║ int8 ║ -128 to 127 ║
║ int16 ║ -32,768 to 32,767 ║
║ int32 ║ -2,147,483,648 to 2,147,483,647 ║
║ int64 ║ -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 ║
╚═══════╩═════════════════════════════════════════════════════════╝
```

Notice the `int64`

range. You may have seen these numbers somewhere before. 🌚 Back when Game Center was a thing...

### Using strings to represent numbers

What we’re going to do is create our own number type. A type that can handle operations on obscenely large numbers, and we’re going to use `String`

s to do this.

Currently there’s no way to add, subtract, multiply or divide integers with strings directly in Swift. So we need to construct our own type to handle this.

We’ll start out with a new struct and call it `BigInt`

.

```
struct BigInt {
var value: String
}
```

We’ll start out with a variable called `value`

. There's also no need to create an initializer because Swift will provide this for us.

### Calculations

Our BigInt is pretty useless without being able to perform a few calculations. So lets jump right into something a little tricky like multiplication.

We’ll use the same method you did when learning how to multiply larger numbers on paper in school.

We start by splitting both values into arrays, where a single character is mapped to each index. The arrays are then reversed to make things a little easier. Finally we loop over both arrays, and multiply the single digits found at each index with each other.

```
func multiply(left: String, right: String) -> String {
var leftCharacterArray = left.characters.reversed().map { Int(String($0))! }
var rightCharacterArray = right.characters.reversed().map { Int(String($0))! }
var result = [Int](repeating: 0, count: leftCharacterArray.count+rightCharacterArray.count)
for leftIndex in 0..<leftCharacterArray.count {
for rightIndex in 0..<rightCharacterArray.count {
let resultIndex = leftIndex + rightIndex
result[resultIndex] = leftCharacterArray[leftIndex] * rightCharacterArray[rightIndex] + (resultIndex >= result.count ? 0 : result[resultIndex])
if result[resultIndex] > 9 {
result[resultIndex + 1] = (result[resultIndex] / 10) + (resultIndex+1 >= result.count ? 0 : result[resultIndex + 1])
result[resultIndex] -= (result[resultIndex] / 10) * 10
}
}
}
result = Array(result.reversed())
return result.map { String($0) }.joined(separator: "")
}
multiply(left: "2844858348834855723432430", right: "134534523453454540998798789")
```

There’s a lot going on here, you be fine to copy and paste it into a playground if you want a closer look at what’s going on.

This method isn’t the most performant or safest piece of code.

There’s also nothing stopping someone from entering a character that isn’t a number, which would of course result in a crash.

Now this is just a stand alone function. Which really could just be added anywhere within our project and do a good job as it is. However, we want something that will work with our `BigInt`

type.

We want to be able to do something like this:

```
let int1 = BigInt("10")
let int2 = BigInt("5")
let product = int1 * int2
```

### BigInt

Alright so let’s add the function to our struct and alter it a bit to make it more to our liking.

```
struct BigInt {
var value: String
func multiply(right: String) -> String {
// We'll change this line to use value
var leftCharacterArray = value.characters.reversed().map { Int(String($0))! }
var rightCharacterArray = right.characters.reversed().map { Int(String($0))! }
...
// Now we can do this
let int1 = BigInt(value: "34")
let int2 = BigInt(value: "45")
let product = int1.multiply(int2.value)
```

Close but still doesn’t give us what we’re after.

Let’s remove the `String`

requirement and pass our `BigInt`

right into our multiply function.

```
func multiply(right: BigInt) -> BigInt {
var a1 = value.characters.reversed().map { Int(String($0))! }
var a2 = right.value.characters.reversed().map { Int(String($0))! }
...
...
// And change the last line
return BigInt(value: result.map { String($0) }.joined(separator: ""))
}
// Our calculation now looks like this.
let int1 = BigInt(value: "34")
let int2 = BigInt(value: "45")
let product = int1.multiply(int2)
```

A bit cleaner, but lets go all the way and define our own `*`

operator.

### Operator Overloading `*`

All you need to do is add this line somewhere outside our `BigInt`

struct.

`func * (left: BigInt, right: BigInt) -> BigInt { return left.multiply(right) }`

Operator overloading allows you to change how existing operators behave with types that both already exist (Int, Float, String), and any custom types you have created. In this example, we’re letting our program know how to multiply two BigInt types the same way we would any other primitive number type.

### Finally

This is what it should all look like once you’re done.

```
import UIKit
import Foundation
struct BigInt {
var value: String
func multiply(right: BigInt) -> BigInt {
var leftCharacterArray = value.characters.reversed().map { Int(String($0))! }
var rightCharacterArray = right.value.characters.reversed().map { Int(String($0))! }
var result = [Int](repeating: 0, count: leftCharacterArray.count+rightCharacterArray.count)
for leftIndex in 0..<leftCharacterArray.count {
for rightIndex in 0..<rightCharacterArray.count {
let resultIndex = leftIndex + rightIndex
result[resultIndex] = leftCharacterArray[leftIndex] * rightCharacterArray[rightIndex] + (resultIndex >= result.count ? 0 : result[resultIndex])
if result[resultIndex] > 9 {
result[resultIndex + 1] = (result[resultIndex] / 10) + (resultIndex+1 >= result.count ? 0 : result[resultIndex + 1])
result[resultIndex] -= (result[resultIndex] / 10) * 10
}
}
}
result = Array(result.reversed())
while result.count > 0 && result.first == 0 {
result.removeFirst(1)
}
return BigInt(value: result.map { String($0) }.joined(separator: ""))
}
}
func * (left: BigInt, right: BigInt) -> BigInt { return left.multiply(right: right) }
```

Multiplying two `BigInts`

together should be as simple as:

```
let int1 = BigInt(value: "34757377374573285823949593499549646311234")
let int2 = BigInt(value: "45123498348958923845838948528381283721377123454345")
let product = int1 * int2
// result: 1568374460575699918065222772187576926314538959488859994856690985365041943440429553059611730
```

There you have it. It’s not perfect, but it does give you an idea of how we can work around some of the hardware restrictions we face as developers.