Print number as reduced fraction in R
fractions() in the MASS package does just that:
> library(MASS)
> fractions(.14)
[1] 7/50
Function in R to convert a decimal to a fraction with a specified denominator
Just in case you need to use a more simplified version of the above function
f = function(x, den) {paste0(round(x * den), "/", den)}
x <- c(0.55, 0.246, 0.767)
f(x, 10)
[1] "6/10" "2/10" "8/10"
How to format a number as percentage in R?
Even later:
As pointed out by @DzimitryM, percent()
has been "retired" in favor of label_percent()
, which is a synonym for the old percent_format()
function.
label_percent()
returns a function, so to use it, you need an extra pair of parentheses.
library(scales)
x <- c(-1, 0, 0.1, 0.555555, 1, 100)
label_percent()(x)
## [1] "-100%" "0%" "10%" "56%" "100%" "10 000%"
Customize this by adding arguments inside the first set of parentheses.
label_percent(big.mark = ",", suffix = " percent")(x)
## [1] "-100 percent" "0 percent" "10 percent"
## [4] "56 percent" "100 percent" "10,000 percent"
An update, several years later:
These days there is a percent
function in the scales
package, as documented in krlmlr's answer. Use that instead of my hand-rolled solution.
Try something like
percent <- function(x, digits = 2, format = "f", ...) {
paste0(formatC(100 * x, format = format, digits = digits, ...), "%")
}
With usage, e.g.,
x <- c(-1, 0, 0.1, 0.555555, 1, 100)
percent(x)
(If you prefer, change the format from "f"
to "g"
.)
How to output fraction instead of decimal number?
You can't. You would need to write a class dedicated to holding rational numbers (i.e. fractions). Or maybe just use the Boost Rational Number library.
How to convert floats to human-readable fractions?
I have found David Eppstein's find rational approximation to given real number C code to be exactly what you are asking for. Its based on the theory of continued fractions and very fast and fairly compact.
I have used versions of this customized for specific numerator and denominator limits.
/*
** find rational approximation to given real number
** David Eppstein / UC Irvine / 8 Aug 1993
**
** With corrections from Arno Formella, May 2008
**
** usage: a.out r d
** r is real number to approx
** d is the maximum denominator allowed
**
** based on the theory of continued fractions
** if x = a1 + 1/(a2 + 1/(a3 + 1/(a4 + ...)))
** then best approximation is found by truncating this series
** (with some adjustments in the last term).
**
** Note the fraction can be recovered as the first column of the matrix
** ( a1 1 ) ( a2 1 ) ( a3 1 ) ...
** ( 1 0 ) ( 1 0 ) ( 1 0 )
** Instead of keeping the sequence of continued fraction terms,
** we just keep the last partial product of these matrices.
*/
#include <stdio.h>
main(ac, av)
int ac;
char ** av;
{
double atof();
int atoi();
void exit();
long m[2][2];
double x, startx;
long maxden;
long ai;
/* read command line arguments */
if (ac != 3) {
fprintf(stderr, "usage: %s r d\n",av[0]); // AF: argument missing
exit(1);
}
startx = x = atof(av[1]);
maxden = atoi(av[2]);
/* initialize matrix */
m[0][0] = m[1][1] = 1;
m[0][1] = m[1][0] = 0;
/* loop finding terms until denom gets too big */
while (m[1][0] * ( ai = (long)x ) + m[1][1] <= maxden) {
long t;
t = m[0][0] * ai + m[0][1];
m[0][1] = m[0][0];
m[0][0] = t;
t = m[1][0] * ai + m[1][1];
m[1][1] = m[1][0];
m[1][0] = t;
if(x==(double)ai) break; // AF: division by zero
x = 1/(x - (double) ai);
if(x>(double)0x7FFFFFFF) break; // AF: representation failure
}
/* now remaining x is between 0 and 1/ai */
/* approx as either 0 or 1/m where m is max that will fit in maxden */
/* first try zero */
printf("%ld/%ld, error = %e\n", m[0][0], m[1][0],
startx - ((double) m[0][0] / (double) m[1][0]));
/* now try other possibility */
ai = (maxden - m[1][1]) / m[1][0];
m[0][0] = m[0][0] * ai + m[0][1];
m[1][0] = m[1][0] * ai + m[1][1];
printf("%ld/%ld, error = %e\n", m[0][0], m[1][0],
startx - ((double) m[0][0] / (double) m[1][0]));
}
How would I make a new fraction if a fraction cannot be simplified?
- Method
decimal()
in classFraction
is not used, so I removed it. - Rather than recursively call method
getAGoodFraction()
when the GCD value is 1, use a loop. - Rather than create a new
Fraction
object each time the randomly generated numerator is greater than the randomly generated denominator, use methodssetNumerator()
andsetDenominator()
. That's what they're for. - There is no need to call method
simplify()
in methodgetAGoodFraction()
. Just return the fraction. Because the GCD is not equal to 1, you know it can be simplified.
Compare the following code with yours.
Note that I added a main()
method to class Fraction
so as to be able to run the code. And I also changed method gcd()
due to the comment to your question from @KevinAnderson.
import java.util.Random;
public class Fraction {
private int numerator;
private int denominator;
public Fraction() {
this(0, 1);
}
public Fraction(int number) {
this(number, 1);
}
public Fraction(Fraction frac) {
this(frac.getNumerator(), frac.getDenominator());
}
public Fraction(int num, int denom) {
setNumerator(num);
setDenominator(denom);
}
public static int gcd(int m, int n) {
int factor = m;
int r = n % factor;
while (r != 0 && factor > 1) {
r = n % --factor;
if (r == 0) {
r = m % factor;
}
}
return factor;
}
public int getDenominator() {
return denominator;
}
public int getNumerator() {
return numerator;
}
public void setDenominator(int denom) {
if (denom == 0) {
System.err.println("Fatal Error");
System.exit(1);
}
denominator = denom;
}
public void setNumerator(int num) {
numerator = num;
}
public Fraction simplify() {
int num = getNumerator();
int denom = getDenominator();
int gcd = gcd(num, denom);
Fraction simp = new Fraction(num / gcd, denom / gcd);
return simp;
}
public String toString() {
return getNumerator() + "/" + getDenominator();
}
public static void main(String[] args) {
SimpleFracBoxes sfb = new SimpleFracBoxes(10);
sfb.makeTheFractions();
System.out.println(sfb.getFractions());
}
}
class SimpleFracBoxes {
private int numberOfFractions = 0;
private String result = "";
Random myRandom = new Random();
int min = 1;
int max = 100000;
public SimpleFracBoxes() {
}
public SimpleFracBoxes(int nOFracs) {
numberOfFractions = nOFracs;
}
//makes the fractions
public void makeTheFractions() {
for (int i = 0; i < numberOfFractions; i++) {
Fraction frac = getAGoodFraction();
Fraction frac2 = frac.simplify();
result += String.format("%" + String.valueOf(numberOfFractions).length() + "d. %5d/%5d simplifies to %5d/%5d%n",
(i + 1),
frac.getNumerator(),
frac.getDenominator(),
frac2.getNumerator(),
frac2.getDenominator());
}
}
// creates a fraction that can be divided
private Fraction getAGoodFraction() {
int gcd = 1;
Fraction frac = new Fraction();
while (gcd == 1) {
do {
frac.setNumerator(myRandom.nextInt(max - min));
frac.setDenominator(myRandom.nextInt(max - min));
} while (frac.getNumerator() >= frac.getDenominator());
int num = frac.getNumerator();
int denom = frac.getDenominator();
gcd = Fraction.gcd(num, denom);
}
return frac;
}
public String getFractions() {
return result;
}
}
Here is a sample output produced when running the above code.
1. 64480/84728 simplifies to 8060/10591
2. 33376/79317 simplifies to 4768/11331
3. 50944/97026 simplifies to 25472/48513
4. 21339/45510 simplifies to 7113/15170
5. 35884/38628 simplifies to 8971/ 9657
6. 15148/17199 simplifies to 2164/ 2457
7. 72670/95005 simplifies to 14534/19001
8. 19810/44730 simplifies to 283/ 639
9. 61790/63956 simplifies to 30895/31978
10. 4824/ 5352 simplifies to 201/ 223
Related Topics
Lookup Values Corresponding to the Closest Date
Subset Dataframe Such That All Values in Each Row Are Less Than a Certain Value
Referring to Variables by Name in a Dplyr Function Returns Object Not Found Error
How to Compare a Value in a Column to the Previous One Using R
Multiply Permutations of Two Vectors in R
How Many Non-Na Values in Each Row for a Matrix
Clustering Algorithm for Obtaining Equal Sized Clusters
R "For Loop" Error Messages {}
Using Ggplot for Scattering Dots
Filter Based on Number of Distinct Values Per Group
Customizing the Sankey Chart to Cater Large Datasets
How to Learn How to Write C Code to Speed Up Slow R Functions
R: How to Get the Last Element from Each Group
R: Expand and Fill Data Frame by Date in Series
Rank a Vector Based on Order and Replace Ties with Their Average