# Haskell Course - Lesson 3 - Numbers

We'll study numbers first because they are one of the most useful types in Haskell. After this lesson, you'll understand 4 new types and learn how to use Haskell as your personal calculator. 🤓

## Common numeric types in Haskell

Not all numbers are the same. And in Haskell, we have four different numeric types: `Int`

, `Integer`

, `Float`

, and `Double`

.

`Int`

and `Integer`

**Both Int and Integer are types that represent whole numbers** (i.e.,

`3`

can be an `Int`

or `Integer`

, but `3.2`

can't).The difference between `Int`

and `Integer`

is the size of the numbers that it can store. ** Integer can hold numbers as big or small as your computer can handle. But Int has a maximum value of 2** (that's 2x2x2x2x2... 63 times 👀, big enough for most cases, if you ask me)

^{63}

**and a minimum value of -2**.

^{63}I assume that you can do the math in your head to know how big is that number.

Just kidding 🤣 , we can ask Haskell to do the math for us. Open `ghci`

in your terminal (like we saw in lesson 1), write `2^62`

, and hit enter:

```
2^62 -- This will give you: 4611686018427387904
```

Haskell calculates the number for us! Awesome! Now, let's indicate that this number "has type of" `Int`

and try again:

```
2^62 :: Int -- This will also give you: 4611686018427387904
```

So far, so good. Now, let's try with a bigger number. Let's say 2^{64}:

```
2^64 :: Int -- Oh no! This will give you: 0! 👀
```

You can try with larger numbers, too! As you can see, numbers greater than 2^{63} are too big for `Int`

and are lost. But, if we try one of those numbers as `Integer`

, we get the correct result:

```
2^69 :: Integer -- This will give you: 590295810358705651712 😏
```

There you go! 😎 No more unexpected zeroes.

So, **why do we need Int if Integer can do the same and has no limits?** Because

`Int`

is more efficient. The program runs faster if we use `Int`

.**What does all this mean to you?**

- If you know you're going to work with small (smaller than ±2
^{63}) whole numbers, use`Int`

. Else, use`Integer`

. - If a function returns an
`Int`

or`Integer`

, you can be sure that it'll be a whole number.

But what about the rest of the numbers? What about numbers with decimal point (with fractional value) like 4.5?

`Float`

and `Double`

Both `Float`

and `Doube`

are real

#### Floating-point number

A floating-point number is one where the position of the decimal point can "float" rather than being in a fixed position within a number. Examples of floating-point numbers are 1.23, 87.425, and 9039454.2.

The difference is the level of precision that they have. `Float`

has

#### Single precision floating-point

Basic format of floating-point number that uses ~7 decimal digits to represent the number. Usually occupying 32 bits in computre memory.

`Double`

has (you guessed it) double the `Float`

's precision.Theoretically, the reasons as to when to use one or de other are somewhat analogous to the `Int`

and `Integer`

cases. `Double`

has double the precision but hogs more memory because it uses twice as many bits to represent numbers.

Recommendation based on real-world use: Don't use `Float`

. Use `Double`

. There's rarely a speed disadvantage in modern computers, and **with Double, you are much less likely to shoot yourself in the foot with rounding errors**.

Let's see what happens if I want to show the first 20 digits of pi (π) in `ghci`

:

```
3.14159265358979323846 :: Float -- Result: 3.1415927
```

With `Float`

, I get 7 digits after the point.

```
3.14159265358979323846 :: Double -- Result: 3.141592653589793
```

With `Double`

I get 15 digits after the point (double the previous precision).

And what if I don't specify the type?

```
3.14159265358979323846 -- Result: 3.141592653589793
```

Haskell assumes that you want the best precision possible and infers that you want to use a `Double`

.

Ok. Those are Haskells standard numeric types. Now let's do some simple calculations!

## Doing some simple calculations

Here are a few math operations in Haskell and its correspondent symbol and example:

Operation | Haskell Symbol | Example |
---|---|---|

Addition | + | 3 + 2 |

Subtraction | - | 3 - 2 |

Multiplication | * | 3 * 2 |

Division | / | 3 / 2 |

Exponential | ^ | 4 ^ 3 |

Remember that operations have an order (division before addition and such). And in Haskell—the same as in maths—you can alter the order by applying parenthesis:

6 + 4 / 2 = 8

(6 + 4) / 2 = 5

Now, we can use `ghci`

as our personal calculator.

### Calculating the volume of a cube

The formula to calculate the volume of a cube is `volume = side`

. This means that to obtain the volume of a cube, we just need to calculate the cube of its side. If we have a cube with 2 meters (2m) of side length, the volume of the cube will be: ^{3}`side`

.^{3} = 2^{3} = 8

And to calculate the volume of a cube of side length 3m, we have to write:

```
3^3 -- That will give me a volume of 27m3
```

Note: *You can navigate through everything you executed in ghci using your arrow keys! Up goes back to previous expressions, and down goes forward to newer expressions*.

Ok, that was the warm-up.

`8^3`

= 512m^{3}

I know, I know. That was too easy. Let's do something more interesting.

### Increasing the difficulty

I'll provide the expression in the form of a sentence, and you have to translate it into a valid Haskell expression in GHCi and check the result:

`(22-13)/3`

= 3.0

`12/4 + 4^2`

= 19.0

`3^9 - 943*500`

= -451817

Notice that Haskell returns the first and second results as a floating-point number (`.0`

) even if the results are whole numbers. But, in the last one, Haskell returns a whole number (without `.0`

). Why is that?

Because Haskell knows (before calculating the result) that if you add two whole numbers, the result will always be a whole number. Same with subtraction and exponential. But there are many cases when a division of whole numbers gives you fractional numbers (i.e., `3/2`

gives you `1.5`

). So, Haskell makes sure that the division never fails by transforming the numbers to `Float`

or `Double`

before dividing.

We'll learn the specifics of how Haskell does this in the "Type classes" lesson.

Ok, we're going to stop here. But you're not done yet! Make sure to complete this week's homework! See ya in the next lesson! 💪😄

## Homework

- Get familiar with the order of operations and take a peek at the programming languages section.

### 2. Fahrenheit to Celsius

Celsius (ºC)—also referred to as centigrade—is the most common non-scientific unit of temperature. But, the US still uses Fahrenheit (ºF). Let's say that you have friends in the US and, when chatting, they always comment about their temperature in Fahrenheit. You got tired of doing the math in your head, and you decide to use Haskell.

This is the formula to transform from Fahrenheit to Celsius: `Tc = (Tf - 32)*5/9`

. Where `Tc`

is the temperature in Celsius (the result) and `Tf`

is the temperature in Fahrenheit. Using only `ghci`

transform the temperatures to Celsius:

- How many ºC is
`100`

ºF? - How many ºC is
`32`

ºF? - How many ºC is
`212`

ºF?

You are doing great! With each lesson, you get closer and closer to becoming a full-fledged programmer! 🔥 Next lesson, we'll learn about characters, lists, and Strings! See you there! 😄

*PD: If you find this course valuable, please share it so more people can learn!* 😄