-
-
Notifications
You must be signed in to change notification settings - Fork 194
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
594515b
commit 08ab682
Showing
14 changed files
with
770 additions
and
56 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,70 +1,183 @@ | ||
# Haskell Built-in Numeric Types | ||
# Numbers | ||
|
||
## Numbers | ||
|
||
Haskell's standard library, known as ***Prelude***, defines most basic numeric types: fixed sized integers (`Int`), arbitrary precision integers (`Integer`), single precision floating (`Float`), and double precision floating (`Double`). | ||
Other numeric types such as rationals and complex numbers are defined in additional libraries. | ||
Haskell has a type, `Num`, which is the base type for all numeric types. | ||
There are four main sub-types inside the Number type: [`Int`][int], [`Integer`][integer], [`Double`][double] and [`Float`][float]. | ||
|
||
There are two types of integers types in Haskell, which represents whole numbers. | ||
`Int` is a fixed-size integer, while `Integer` is an arbitrary precision integer. | ||
`Integer`s hold any number no matter how big, up to the limit of your machine's memory, while `Int` corresponds to the set of positive and negative integers that can be expressed in 32 or 64 bits (guaranteed at least -2^29 to 2^29). | ||
|
||
Note that when writting negative numbers, you should use parentheses to avoid ambiguity. | ||
|
||
```haskell | ||
1 | ||
|
||
(-1) | ||
``` | ||
|
||
`Float` corresponds to the set of real numbers, limited by the precision of the computer. | ||
Operations defined on numbers usually work on one type or the other, but not both. | ||
`Double` is a floating-point number with double precision. | ||
|
||
```haskell | ||
10.5 | ||
``` | ||
|
||
## Converting between integers and floats | ||
|
||
Using the `toFloat` function, allows you to convert an `Int` or `Integer` to a `Float`. | ||
|
||
```haskell | ||
toFloat 1 | ||
-- -> 1.0 | ||
``` | ||
|
||
There is also `fromIntegral` which converts any number types to the inferred type number type needed. | ||
|
||
```haskell | ||
fromIntegral 1 | ||
-- -> 1.0 | ||
``` | ||
|
||
To convert a `Float` to an `Int`, you can use the `round`, `floor`, or `ceiling` functions. | ||
The `round` function rounds to the nearest integer, `floor` rounds down, and `ceiling` rounds up. | ||
|
||
```haskell | ||
round 1.5 | ||
-- -> 2 | ||
|
||
floor 1.5 | ||
-- -> 1 | ||
|
||
Functions to convert between `Float` and `Integer` include, among others, `toFloat` which converts `Int`/`Integer` to `Float` and `ceiling` which converts a `Float` to an `Int`. | ||
ceiling 1.5 | ||
-- -> 2 | ||
``` | ||
|
||
## Arithmetic operators | ||
|
||
Haskell has three "raise to the power" operators which work differently and take different argument types. | ||
You can use the [basic arithmetic operators][math] on the numeric types. | ||
The operators are `+`, `-`, `*`, `/`, and `%`. | ||
When using these operators, the types of the numbers must match. | ||
The `fromIntegral` function will convert so that the types match. | ||
|
||
- `**` Takes two **floating point numbers** and uses logarithms to compute the power. | ||
- `^^` Takes a **floating point** and raises it to a positive or negative **integer** power. | ||
- `^` Takes **any numerical type** and raises it to a **positive integer** power. | ||
### Addition & Subtraction & Multiplication | ||
|
||
The `+` operator is used for addition, the `-` operator is used for subtraction, and the `*` operator is used for multiplication. | ||
|
||
Conversion from an integer type (`Int` or `Integer`) to any other numeric type is done using the function `fromIntegral`. | ||
The target type is inferred automatically. | ||
For example: | ||
| Operator | Example | | ||
| -------- | -------------- | | ||
| `+` | `4 + 6 => 10` | | ||
| `-` | `15 - 10 => 5` | | ||
| `*` | `2 * 3 => 6` | | ||
|
||
### Division | ||
|
||
Division is used to divide numbers. | ||
The `/` operator is used for division. | ||
The result will always be a float. | ||
|
||
```haskell | ||
n :: Integer | ||
n = 6 | ||
x :: Float | ||
x = fromIntegral n --> x = 6.0 | ||
|
||
m :: Int | ||
m = 7 | ||
y :: Double | ||
y = fromIntegral m --> y = 7.0 | ||
4.0 / 2.5 | ||
-- -> 1.6 | ||
|
||
4 / 2 | ||
-- -> 2.0 | ||
``` | ||
|
||
Division of integers is a little complicated. | ||
If you use the ordinary `/` operator on integers, then you will get an error message (although the expression `4/3` does work because Haskell helpfully promotes literal integers to floats where necessary). | ||
Instead, integer division is done using a collection of named operators. | ||
~~~~exercism/caution | ||
In some programming languages, when dividing by zero, the result will be an error. | ||
Haskell has a neat trick with operators: you can take any function that takes two arguments and use it like an operator by enclosing the name in back-ticks. | ||
So the following two lines mean exactly the same thing: | ||
In Haskell, when dividing by zero, the result is `Infinity` or `-Infinity`. | ||
The only exception is dividing zero by zero, resulting in `NaN` (Not a Number). | ||
```haskell | ||
d = 7 `div` 3 | ||
d = div 7 3 | ||
1 / 0 | ||
-- -> Infinity | ||
(-1) / 0 | ||
-- -> -Infinity | ||
0 / 0 | ||
-- -> NaN | ||
``` | ||
~~~~ | ||
|
||
## Integer division | ||
|
||
Integer division is used to divide numbers and get the whole part of the result. | ||
The result will always be rounded down to an Int. | ||
|
||
```haskell | ||
2 `div` 2 | ||
-- -> 2 | ||
|
||
5 `div` 2 | ||
-- -> 2 | ||
``` | ||
|
||
With that in mind, here are the integer division operators: | ||
~~~~exercism/caution | ||
Dividing by zero when using integer division results in a Exception. | ||
This is different from normal division. | ||
~~~~ | ||
|
||
### Modulus | ||
|
||
- `quot`: Returns the quotient of the two numbers. | ||
This is the result of division which is then truncated towards zero. | ||
- `rem`: Returns the remainder from the quotient. | ||
- `div`: Similar to `quot`, but is rounded down towards minus infinity. | ||
- `mod`: Returns the modulus of the two numbers. | ||
This is similar to `rem`, but has different rules when `div` returns a negative number. | ||
Modulus is used to get the remainder of a division. | ||
The `mod` operator is used for modulus. | ||
|
||
Just as you can convert a function with two arguments into an operator, you can convert an operator into a function with two arguments by putting it in parentheses. | ||
So the following two lines mean the same thing: | ||
```haskell | ||
5 `mod` 2 | ||
-- -> 1 | ||
|
||
5 `mod` 3 | ||
-- -> 2 | ||
``` | ||
|
||
~~~~exercism/caution | ||
Dividing by zero when using modulo results in an Exception. | ||
This is different from normal division. | ||
```haskell | ||
(+) 3 4 | ||
3 + 4 | ||
1 `mod` 0 | ||
# Exception: divide by zero | ||
``` | ||
~~~~ | ||
|
||
## Exponentiation | ||
|
||
Haskell has three "raise to the power" operators which work differently and take different argument types. | ||
|
||
- `**` Takes two **floating point numbers** and uses logarithms to compute the power. | ||
- `^^` Takes a **floating point** and raises it to a positive or negative **integer** power. | ||
- `^` Takes **any numerical type** and raises it to a **positive integer** power. | ||
|
||
```haskell | ||
3.0 ** 2.1 | ||
-- -> 10.04510856630514 | ||
|
||
2.5 ^^ 2 | ||
-- -> 6.25 | ||
|
||
2 ^ 3 | ||
-- -> 8 | ||
``` | ||
|
||
## Priority and parentheses | ||
|
||
Haskell allows parentheses(`()`), which can be used to group expressions. | ||
This is useful when you want to change the order of operations. | ||
|
||
When using multiple arithmetic operators, the order of operations is the same as in mathematics, also known as [PEMDAS][pemdas]. | ||
It follows the order of parentheses(`()`), exponents(`**`), multiplication(`*`) and division(`/`), and addition(`+`) and subtraction(`-`). | ||
|
||
```haskell | ||
2 + 3 - 4 * 4 | ||
-- -> -11 | ||
|
||
(2 + 3 - 4) * 4 | ||
-- -> 4 | ||
``` | ||
|
||
--- | ||
### Credits: | ||
The above text is modified from __The Haskell 98 Report__ by Simon Peyton Jones, used with permission to copy, distribute and modify for any purpose with this note included. | ||
[pemdas]: https://en.wikipedia.org/wiki/Order_of_operations | ||
[floor]: https://hackage.haskell.org/package/base/docs/Prelude.html#v:floor | ||
[ceiling]: https://hackage.haskell.org/package/base/docs/Prelude.html#v:ceiling |
Oops, something went wrong.