Rationals 2.3.0

This package has a SemVer 2.0.0 package version: 2.3.0+build.238.
dotnet add package Rationals --version 2.3.0                
NuGet\Install-Package Rationals -Version 2.3.0                
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Rationals" Version="2.3.0" />                
For projects that support PackageReference, copy this XML node into the project file to reference the package.
paket add Rationals --version 2.3.0                
#r "nuget: Rationals, 2.3.0"                
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
// Install Rationals as a Cake Addin
#addin nuget:?package=Rationals&version=2.3.0

// Install Rationals as a Cake Tool
#tool nuget:?package=Rationals&version=2.3.0                

Rationals logo Rationals .NET

Implementation of rational number arithmetic for .NET with arbitrary precision.

Build status Tests codecov NuGet version NuGet downloads

var left = (Rational) 1 / 2;
var right = (Rational) 1 / 4;

var sum = left + right; // equals to: 3 / 4

Download

Binaries of the last build can be downloaded on the AppVeyor CI page of the project.

The library is also published on NuGet.org, install using:

PM> Install-Package Rationals

The library can be used since .NET 4.0 or .NET Standard 1.3. It's also CLS compliant to allow use in VB.NET.

Features

  • implicit conversions - rationals integrate seamlessly with other number types
  • unlimited precision - rationals use BigInteger inside
  • canonical form - each rational can have its canonical form (irreducible fraction where denominator is always positive)
  • comparison & equality
  • separate whole and fractional part - any rational number can be separated into a whole part (integer quotient aka result of integer division) and fractional part (reminder of the integral division aka result of modulo operation)
  • continued fraction expansion - expand rational numbers to continued fraction (sequence of coefficients), construct rational numbers from sequence of continued fraction coefficients
  • rational number approximation - approximate floating point numbers (decimal, double, float) as rational numbers with customizable tolerance
  • multiple formatting options - ToString("C") (canonical form), ToString("W") (whole + fractional part), or normal fraction format

Documentation

The Rationals library is an alternative to BigRational found in BCL. Its implementation is quite trivial, it doesn't do any low-level magic to make sure it's the best performer. But it should be easy to use and has few nice features.

Constructors

There are just two constructors to rational numbers. For most scenarios, you might not need to use those constructors directly and rely on the typecasting operators.

// constructor from a whole BigInteger number
var p = new Rational(new BigInteger(3));

// constructor from a BigInteger numerator and denominator
var p = new Rational(new BigInteger(1), new BigInteger(2));

Implicit conversions from other types

Rationals are much easier created by implicit conversions. There exist implicit conversions from: int, uint, short, ushort, long, ulong, byte, sbyte, and BigInteger.

Rational p = 5;

Explicit conversions from other types

There exist explicit operator conversions from decimal, double, and float.

var p = (Rational) 0.5; // equals to: 1/2

Note that sometimes you might not get very nice rational numbers as the output.

var p = (Rational) 0.71428571428M; // equals to: 71428571428/100000000000 (or 17857142857/25000000000 simplified)

However, 0.71428571428 is almost exactly 5/7. To actually read the number as 5/7, you have to use the Rational.Approximate function and provide some tolerance.

Approximation

Approximation tries to find the "simplest" rational number for given decimal/floating point number.

The library supports approximation of decimal, double, and float numbers. An optional second tolerance parameter might be given.

var p1 = Rational.Approximate(0.71428571428M);                            // 17857142857/25000000000
var p2 = Rational.Approximate(0.71428571428M, tolerance: 0.00000000001M); // 5/7

var q1 = Rational.Approximate(0.3333);         // 3333/10000
var q2 = Rational.Approximate(0.3333, 0.0001); // 1/3 

Continuous fraction expansion

Rational numbers can be expanded into Continuous fractions. The library can expand any rational number into a such a fraction, the result of this is the sequence of those coefficients.

For example, the rational number 649/200 can be represented as a continuous fraction with coefficients 3, 4, 12, 4, which when used in the formula 3 + 1/(4 + 1/(12 + 1/4)) give the result 649/200.

// compute rational number from continuous fraction coefficients
var p = Rational.FromContinuedFraction(new BigInteger[] { 3, 4, 12, 4 }); // 649/200

// find continuous fraction coefficients for a rational number
var coefficients = ((Rational) 10 / 7).ToContinuedFraction(); // 1, 2, 3

Reducing fractions, canonical form

The library supports reducing (simplifying) fractions. To reduce a fraction, you can use the CanonicalForm property. That returns a rational number that's irreducible, and where also the denominator is always positive. Canonical form of zero is 0/1.

var p1 = ((Rational) 9 / 12).CanonicalForm;    // 3/4
var p2 = ((Rational) (-9) / 12).CanonicalForm; // -3/4
var p3 = ((Rational) 9 / -12).CanonicalForm;   // -3/4
var p4 = ((Rational) 0 / -12).CanonicalForm;   // 0/1

There should always be just one canonical form of any rational number.

Whole and fractional parts

A rational number x/y can be thought of as having a whole and fractional part a + b/c.

For example, the 14/4 can be written as 3 + 2/4 where 3 is the whole part, and 2/4 is the fractional part.

var r1 = (Rational)14 / 4;
BigInteger a1 = r1.WholePart;   // 3
Rational bc1 = r1.FractionPart; // 2/4

var r2 = (Rational)(-49) / 10;
BigInteger a2 = r2.WholePart;   // -5
Rational bc2 = r2.FractionPart; // 1/10

Explicit conversions to other types

Rational numbers can be explicitly converted to decimal, double, and float decimal numbers. Note that the Rational type has unlimited precision where the types to convert to are limited. As a result of that, there might be some rounding occurring or an overflow.

var p1 = (Rational) 1 / 2;
var x1 = (decimal) p1; // 0.5

var p2 = (Rational) 1 / 3;
var x2 = (double) p2; // 0.33333333333333337

Rational numbers can also be explicitly converted to whole number types int, uint, short, ushort, long, ulong, byte, and sbyte. For these, we only take the whole part of the fractional number:

var p1 = (Rational) 3 / 2;
var x1 = (int) p1; // 1

var p2 = (Rational) (-3) / 2;
var x2 = (int) p2; // -2

BigInteger inspired properties

There are several other useful properties of the rational number that have similar equivalents in BigInteger:

  • .IsZero returns true if the number is equal to 0
  • .IsOne returns true if the is equal to 1
  • .Sign returns an int number (negative, positive, or zero) that indicates the sign of the number
  • .IsPowerOfTwo returns true if the number is a power of two

Overloaded operators

Rational numbers have all the common numeric operators overloaded so that their use in C# is very idiomatic. All of these operators should behave as expected: +, unary -, binary -, *, /, ++, --, ==, !=, <, >, <=, >=.

var p = (Rational) 3 / 4;
var q = (Rational) 1 / 3;
var result = p / q; // 9/4

Mathematical operations

The Rational class has a range of static methods that implement common mathematical operations. Some of these can be used through the corresponding overloaded operators.

var p = (Rational) 3 / 4;
var q = (Rational) 1 / 3;

Rational.Invert(p);      // 4/3
Rational.Negate(p);      // -3/4
Rational.Add(p, q);      // 13/12
Rational.Subtract(p, q); // 5/12
Rational.Multiply(p, q); // 3/12
Rational.Divide(p, q);   // 9/4
Rational.Pow(p, 2);      // 9/16
Rational.Abs(p);         // 3/4
Rational.Log10(p);       // -0.12493873660829985
Rational.Log(p);         // -0.28768207245178079 (base is e)
Rational.Log(p, 2);      // -0.4150374992788437
Rational.Root(p, 2);     // 0.8660254037844386 (square root, result is double)
Rational.RationalRoot((Rational) 9 / 16, 2); // 3/4 (square root, result is rational)

Computing magnitude

Magnitude of a number can be thought of as the exponent of 10 if the number was written in scientific notation.

  • Magnitude of 0 is 0.
  • Magnitude of 5 is 0.
  • Magnitude of 12 is 1.
  • Magnitude of 3988222 is 6.
  • Magnitude of 0.2223 is -1.
  • Magnitude of 0.04 is -2.

To find the magnitude of rational number, use the .Magnitude property.

var p = (Rational) 1 / 11;
int magnitude = p.Magnitude; // -2 

Significant digits

Every rational number has a Digits property that enumerates all significant digits of the rational number. You might want to use this together with the Magnitude property.

Keep in mind that the result of this might be infinite. For example, for the rational number 1/3, it will return an infinite sequence of threes.

((Rational) 200).Digits;                // 2
((Rational) 1/2).Digits;                // 5
((Rational) 1/3).Digits.Take(10);       // 3, 3, 3, 3, 3, 3, 3, 3, 3, 3
((Rational) (-213)/31).Digits.Take(10); // 6, 8, 7, 0, 9, 6, 7, 7, 4, 1
((Rational) 0).Digits;                  // 0

Formatting

Rational numbers can be formatted in three formats passed into the .ToString() method:

  • "F" (default, normal fraction)
    • whole number will be formated as a whole number, e.g. 10/5 as 2.
    • fractional number will be formatted as it is, e.g. 9/5 as 9/5.
  • "C" (canonical fraction)
    • number will be converted to canonical form, and then formatted as "F".
  • "W" (whole + fractional part)`
    • number will be separated as a whole and fractional part and formatted with a space between them, e.g. 9/5 as 1 4/5.

Parsing

The Rational class has 4 different static methods for parsing strings: .Parse, .TryParse, .ParseDecimal, and .TryParseDecimal.

The .Parse and .TryParse methods accept strings in two formats:

  • Fractional format (e.g. 3/4)
  • Whole fractional format (e.g. 5 1/2)

The .ParseDecimal and .TryParseDecimal methods try to parse the string into decimal type and then convert it to Rational. An optional tolerance parameter might be given to parse nicer fractions, as it uses the Approximate function inside.

var p1 = Rational.Parse("7/5");        // 7/5
var p2 = Rational.Parse("1 2/5");      // 7/5
var p3 = Rational.ParseDecimal("1.4"); // 7/5
Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed. 
.NET Core netcoreapp1.0 was computed.  netcoreapp1.1 was computed.  netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard1.3 is compatible.  netstandard1.4 was computed.  netstandard1.5 was computed.  netstandard1.6 was computed.  netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net40 is compatible.  net403 was computed.  net45 was computed.  net451 was computed.  net452 was computed.  net46 was computed.  net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen30 was computed.  tizen40 was computed.  tizen60 was computed. 
Universal Windows Platform uap was computed.  uap10.0 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.
  • .NETFramework 4.0

    • No dependencies.
  • .NETStandard 1.3

  • .NETStandard 2.0

    • No dependencies.
  • net6.0

    • No dependencies.
  • net8.0

    • No dependencies.

NuGet packages (4)

Showing the top 4 NuGet packages that depend on Rationals:

Package Downloads
Peachpie.Library

Peachpie PHP language library functions.

CryptoExchangeClient

Clients for multiple cryptocurrency exchanges. All clients have a shared interface for common actions.

DelSquared.Radicals

.NET implementation of radical expressions enabling radical expression arithmetic.

DoodleDigits.Core

Math library powering Doodle Digits. Takes a string input and returns a number of results.

GitHub repositories (2)

Showing the top 2 popular GitHub repositories that depend on Rationals:

Repository Stars
peachpiecompiler/peachpie
PeachPie - the PHP compiler and runtime for .NET and .NET Core
AnthonyLloyd/CsCheck
Random testing library for C#
Version Downloads Last updated
2.3.0 14,345 11/19/2023
2.2.0 602 10/14/2023
2.1.0 7,288 3/27/2023
2.0.0 44,904 8/21/2021
1.4.1 14,078 7/6/2021
1.4.0 219,334 12/28/2020
1.3.3 433,564 1/15/2019
1.3.2 63,004 9/15/2018
1.3.1 43,813 11/18/2017
1.3.0 1,488 11/11/2017
1.2.1 1,606 3/11/2017
1.2.0 3,232 7/2/2016
1.1.1 1,350 7/2/2016
1.1.0 1,352 7/2/2016
1.0.0 2,004 11/1/2014