D Programming Language 2.0

Last update Sun Mar 20 21:04:26 2011


This module contains an implementation of rational numbers that is templated on the underlying integer type. It can be used with either builtin fixed width integers or arbitrary precision integers. All relevant operators are overloaded for both rational-rational and rational-integer operations.

// Compute pi using the generalized continued fraction approximation.
import std.bigint;

enum maxTerm = 30;

Rational!(BigInt) getTerm(int termNumber) {
    auto addFactor = 2 * termNumber - 1;

    if(termNumber == maxTerm) {
        return rational(BigInt(addFactor));

    auto termNumberSquared = BigInt(termNumber * termNumber);
    auto continued = termNumberSquared / getTerm(termNumber + 1);

    continued += addFactor;
    return continued;

void main() {

    auto pi = rational(BigInt(4)) / getTerm(1);

    // Display the result in rational form.

    // Display the decimal equivalent, which is accurate to 18 decimal places.
    writefln("%.18f", cast(real) pi);

David Simcha

Boost License 1.0

template isIntegerLike(T)
Checks whether T is structurally an integer, i.e. whether it supports all of the operations an integer type should support. Does not check the nominal type of T. In particular, the following must compile:

T num;
num = 2;
num <<= 1;
num >>= 1;
num += num;
num *= num;
num /= num;
num -= num;
num %= 2;
num %= num;
bool foo = num < 2;
bool bar = num == 2;
All builtin D integers and std.bigint.BigInt are integer-like by this definition.

template isAssignable(T,U)
Returns true iff a value of type U can be assigned to a variable of type T.

static assert(isAssignable!(long, int));
static assert(!isAssignable!(int, long));
static assert(isAssignable!(const(char)[], string));
static assert(!isAssignable!(string, char[]));

template CommonInteger(I1,I2) if (isIntegerLike!(I1) && isIntegerLike!(I2))
Returns a common integral type between I1 and I2. This is defined as the type returned by I1.init * I2.init.

Rational!(CommonInteger!(I1,I2)) rational(I1, I2)(I1 i1, I2 i2);
Implements rational numbers on top of whatever integer type is provided. The integer type used may be any type that behaves as an integer. Specifically, isIntegerLike must return true, the integer type must have value semantics, and the semantics of all integer operations must follow the normal rules of integer arithmetic.

auto r1 = rational( BigInt("314159265"), BigInt("27182818"));
auto r2 = rational( BigInt("8675309"), BigInt("362436"));
r1 += r2;
assert(r1 == rational( BigInt("174840986505151"),

// Print result.  Prints:
// "174840986505151 / 4926015912324"

// Print result in decimal form.  Prints:
// "35.4934"
writeln(cast(real) result);

Rational!(I) rational(I)(I val);
Overload for creating a rational that initially has an integer value.

auto r = rational(5);
writeln(r);  // Prints 5 / 1

struct Rational(Int) if (isIntegerLike!(Int));
The struct that implements rational numbers. All relevant operators (addition, subtraction, multiplication, division, exponentiation by a non-negative integer, equality and comparison) are overloaded. The second operand for all binary operators except exponentiation may be either another Rational or another integer type.

typeof(this) invert();
Fast inversion, equivalent to 1 / this.

template opCast(F) if (isFloatingPoint!(F))
Convert to floating point representation.

F opCast();
Convert to floating point representation.

template opCast(I) if (isIntegerLike!(I) && is(typeof(cast(I)Int.init)))
Casts this to an integer by truncating the fractional part. Equivalent to integerPart, and then casting it to type I.

I opCast();
Casts this to an integer by truncating the fractional part. Equivalent to integerPart, and then casting it to type I.

Int num();
Returns the numerator.

Int denom();
Returns the denominator.

Int integerPart();
Returns the integer part of this rational, with any remainder truncated.

typeof(this) fractionPart();
Returns the fractional part of this rational.

string toString();
Returns a string representation of this in the form this.num / this.denom.

Rational!(Int) toRational(Int)(real floatNum, real epsilon = 1e-08);
Convert a floating point number to a Rational based on integer type Int. Allows an error tolerance of epsilon. (Default epsilon = 1e-8.)

epsilon must be greater than 1.0L / long.max.

Exception on infinities, NaNs, numbers with absolute value larger than long.max and epsilons smaller than 1.0L / long.max.

// Prints "22 / 7".
writeln( toRational!int( PI, 1e-1));

CommonInteger!(I1,I2) gcf(I1, I2)(I1 num1, I2 num2);
Find the greatest common factor of num1 and num2 using Euclid's Algorithm.

CommonInteger!(I1,I2) lcm(I1, I2)(I1 num1, I2 num2);
Find the least common multiple of num1, num2.

Int iAbs(Int)(Int num1);
Absolute value function that should gracefully handle any reasonable BigInt implementation.

Int floor(Int)(Rational!(Int) r);
Returns the largest integer less than or equal to r.

Int ceil(Int)(Rational!(Int) r);
Returns the smallest integer greater than or equal to r.

Int round(Int)(Rational!(Int) r);
Round r to the nearest integer. If the fractional part is exactly 1 / 2, r will be rounded such that the absolute value is increased by rounding.