# fracture Convert decimals to fractions in R

## Installation

You can install the released version of fracture from CRAN with:

``install.packages("fracture")``

or the development version from GitHub with:

``````# install.packages("remotes")
remotes::install_github("rossellhayes/fracture")``````

## Usage

### Convert decimals to a character vector of fractions

fracture converts decimals into fractions.

``````fracture(0.5)
#>  1/2

fracture((1:11) / 12)
#>   1/12  1/6   1/4   1/3   5/12  1/2   7/12  2/3   3/4   5/6   11/12``````

#### Common denominators

``````fracture((1:11) / 12, common_denom = TRUE)
#>   1/12  2/12  3/12  4/12  5/12  6/12  7/12  8/12  9/12  10/12 11/12``````

#### Base-10 denominators

``````fracture(1 / (2:12), base_10 = TRUE)
#>   5/10             3333333/10000000 25/100           2/10
#>   1666667/10000000 1428571/10000000 125/1000         1111111/10000000
#>   1/10             909091/10000000  833333/10000000``````

#### Maximum denominators

``````fracture(1 / (2:12), base_10 = TRUE, max_denom = 1000)
#>   5/10     333/1000 25/100   2/10     167/1000 143/1000 125/1000 111/1000
#>   1/10     91/1000  83/1000

fracture(1 / (2:12), base_10 = TRUE, common_denom = TRUE, max_denom = 1000)
#>   500/1000 333/1000 250/1000 200/1000 167/1000 143/1000 125/1000 111/1000
#>   100/1000 91/1000  83/1000``````

#### Mixed fractions

``````fracture((1:9) / 3, mixed = TRUE)
#>  "1/3"   "2/3"   "1"     "1 1/3" "1 2/3" "2"     "2 1/3" "2 2/3" "3"``````

### Convert decimals to a fraction matrix

For more advanced work, you may prefer to work with a fraction matrix:

``````frac_mat((1:11) / 12)
#>             [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9] [,10] [,11]
#> numerator      1    1    1    1    5    1    7    2    3     5    11
#> denominator   12    6    4    3   12    2   12    3    4     6    12``````

`frac_mat()` accepts all the same arguments as `fracture()`.

When mixed fractions are used, `frac_mat()` has three rows:

``````frac_mat((1:9) / 3, mixed = TRUE, common_denom = TRUE)
#>             [,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8] [,9]
#> integer        0    0    1    1    1    2    2    2    3
#> numerator      1    2    0    1    2    0    1    2    0
#> denominator    3    3    3    3    3    3    3    3    3``````

### Math with `fracture`s

`fracture`s are implemented using an S3 class. This means we can perform mathematical operations on them like real fractions.

``````fracture(0.25) * 2
#>  1/2

fracture(0.25) + fracture(1/6)
#>  5/12``````

### Stylish `fracture`s

`frac_style()` uses Unicode to provide stylish formatting for inline fractions.

```r frac_style(pi, mixed = TRUE, max_denom = 500)```

3 ¹⁶/₁₁₃

### Just a fun example

Use fracture to find the best approximations of π for each maximum denominator.

``````unique(purrr::map_chr(1:50000, ~ fracture(pi, max_denom = .x)))
#>  "3/1"          "22/7"         "333/106"      "355/113"      "103993/33102"
#>  "104348/33215"``````

Isn’t is interesting that there’s such a wide gap between ³⁵⁵/₁₁₃ and ¹⁰³⁹⁹³/₃₃₁₀₂?

fracture is implemented using optimized C++ with Rcpp and S3 methods. This allows it to run faster than alternatives like `MASS::fractions()` or `fractional::fractional()`.*

``````# Performance with a single value
single_benchmark
#> # A tibble: 3 × 6
#>   expression                            min median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr>                          <dbl>  <dbl>     <dbl>     <dbl>    <dbl>
#> 1 print(fracture(x))                1      1         1.84       1       1.33
#> 2 print(MASS::fractions(x))         1.87   1.77      1         26.6     2.00
#> 3 print(fractional::fractional(x))  1.45   1.55      1.18      18.3     1

# Performance with a vector of length 1000
vector_benchmark
#> # A tibble: 3 × 6
#>   expression                         min median `itr/sec` mem_alloc `gc/sec`
#>   <bch:expr>                       <dbl>  <dbl>     <dbl>     <dbl>    <dbl>
#> 1 print(fracture(x))                1      1         2.23      1        1
#> 2 print(MASS::fractions(x))         2.48   1.89      1.27      7.01     1.69
#> 3 print(fractional::fractional(x))  3.47   2.49      1         1.79     1.67``````

* `fractional()` does not compute a decimal’s fractional equivalent until it is printed. Therefore, benchmarking the time to print provides a fairer test of the three packages’ capabilities.

Hex sticker fonts are Source Sans and Hasklig.

Please note that fracture is released with a Contributor Code of Conduct. By contributing to this project, you agree to abide by its terms.