BigFraction

Fork of fraction package.

A Dart/Flutter package about fractions. This fork offers fractions using BigInt for their numerator/denominator.

Difference with the original fraction package

This package uses BigInt instead of int for the numerator and denominator. When dealing with bigger fractions, especially on the web, there is a problem with precision. Using BigInt solves the issue at the cost of using more memory.

The docs below might not be correct.

Working with fractions

You can create an instance of BigFraction using one of its constructors:

  • Default: it just requires the numerator and/or the denominator (as a BigInt).

    BigFraction(BigInt.one, BigInt.two); // 1/2
    BigFraction(BigInt.from(3), BigInt.one); // 3
    
  • from: it just requires the numerator and/or the denominator (as an int).

    BigFraction.from(3, 5); // 3/5
    BigFraction.from(3, 1); // 3
    
  • fromString: requires a String representing a fraction.

    BigFraction.fromString("2/4"); // 2/4
    BigFraction.fromString("-2/4"); // -2/4
    BigFraction.fromString("2/-4"); // Throws an exception
    BigFraction.fromString("-2"); // -2/1
    BigFraction.fromString("/3"); // Error
    
  • fromDouble: converts a double into a fraction. Note that irrational numbers cannot be converted into fractions by definition; the constructor has the precision parameter which decides how precise the representation has to be.

    BigFraction.fromDouble(1.5); // 3/2
    BigFraction.fromDouble(-8.5); // -17/2
    BigFraction.fromDouble(math.pi); // 208341/66317
    BigFraction.fromDouble(math.pi, precision: 1.0e-4); // 333/106
    

    The constant pi cannot be represented as a fraction because it's an irrational number. The constructor considers only precison decimal digits to create a fraction.

Thanks to extension methods you can also create a BigFraction object "on the fly" by calling the toBigFraction() method on a number or a string.

5.toBigFraction(); // 5/1
1.5.toBigFraction(); // 3/2
"6/5".toBigFraction(); // 6/5

Note that a BigFraction object is immutable so methods that require changing the internal state of the object return a new instance. For example, the reduce() method reduces the fraction to the lowest terms and returns a new instance:

final fraction = BigFraction.fromString("12/20"); // 12/20
final reduced = fraction.reduce(); // 3/5

BigFraction strings can be converted from and to unicode glyphs when possible.

BigFraction.fromGlyph("¼"); // BigFraction(1, 4)
BigFraction(1, 2).toStringAsGlyph(); // "½"

You can easily sum, subtract, multiply and divide fractions thanks to arithmetic operators:

final f1 = BigFraction(5, 7);
final f2 = BigFraction(1, 5);

final sum = f1 + f2; // -> 5/7 + 1/5
final sub = f1 - f2; // -> 5/7 - 1/5
final mul = f1 * f2; // -> 5/7 * 1/5
final div = f1 / f2; // -> 5/7 / 1/5

The BigFraction type has a wide API with the most common operations you'd expect to make on a fraction:

BigFraction(10, 2).toDouble();  // 5.0
BigFraction(10, 2).inverse();   // 2/10
BigFraction(1, 15).isWhole;     // false
BigFraction(2, 3).negate();     // -2/3
BigFraction(1, 15).isImproper;  // false
BigFraction(1, 15).isProper;    // true

// Access numerator and denominator by index
final fraction = BigFraction(-7, 12);

print('${fraction[0]}'); // -7
print('${fraction[1]}'); // 12

Any other index value different from 0 and 1 throws a BigFractionException exception. Two fractions are equal if their "cross product" is equal. For example 1/2 and 3/6 are said to be equivalent because 1*6 = 3*2 (and in fact 3/6 is the same as 1/2).

Working with mixed fractions

A mixed fraction is made up of a whole part and a proper fraction (a fraction in which numerator <= denominator). Building a MixedBigFraction object is very easy:

MixedBigFraction(
  whole: 3, 
  numerator: 4, 
  denominator: 7
);

As it happens with fractions, you can use various named constructors as well:

MixedBigFraction.fromDouble(1.5);
MixedBigFraction.fromString("1 1/2");

There also is the possibility to initialize a MixedBigFraction using extension methods:

final mixed = "1 1/2".toMixedBigFraction();

Note that MixedBigFraction objects are immutable exactly like BigFraction objects so you're guaranteed that the internal state of the instance won't change. Make sure to check the official documentation at pub.dev for a complete overview of the API.

Egyptian fractions

An Egyptian fraction is a finite sum of distinct fractions where the numerator is always 1 and, the denominator is a positive number and all the denominators differ from each other. For example:

  • 5/8 = 1/2 + 1/8 (where "1/2 + 1/8" is the egyptian fraction)

In other words, egyptian fractions are a sum of fractions in the form 1/x that represent a proper or an improper fraction. Here's how they can be computed:

final egyptianBigFraction1 = BigFraction(5, 8).toEgyptianBigFraction();
print("$egyptianBigFraction1"); // prints "1/2 + 1/8"

final egyptianBigFraction2 = MixedBigFraction(2, 4, 5).toEgyptianBigFraction();
print("$egyptianBigFraction2"); // prints "1 + 1 + 1/2 + 1/4 + 1/20"

The compute() method returns an iterable.

Notes

Both BigFraction and MixedBigFraction descend from the BigRational type which allows parsing both kind of fractions with a single method call:

// This is a 'BigFraction' object
Rational.tryParse('1/5'); // 1/5

// This is a 'MixedBigFraction' object
Rational.tryParse('2 4/7'); // 2 4/7

// This is 'null' because the string doesn't represent a fraction or a mixed fraction
Rational.tryParse(''); // null

Parsing integer values like Rational.tryParse('3') always returns a BigFraction type but it can easily be converted into a mixed fraction using the BigFraction.toMixedBigFraction method.

Libraries

big_fraction
A package that helps you working with fractions, mixed fractions and egyptian fractions.