วันเสาร์ที่ 26 กรกฎาคม พ.ศ. 2551

Rational for C#

Rational is ratio of 2 integers. It represents fractions of an integer. Most of the time if you deal with rational number, you can use real number (float) instead. But real number has an drawback. It cannot maintain proportion of 2 integers for number with repeating decimal. For example,

(1/20)2 + (1/15)2 - (1/12)2
= (1/400) + (1/225) - (1/144)
= (9/3600) + (16/3600) - (25/3600)
= 0

Now testing with real number:

double x = Math.Pow(1.0 / 20.0, 2.0);
double y = Math.Pow(1.0 / 15.0, 2.0);
double z = Math.Pow(1.0 / 12.0, 2.0);
Console.WriteLine(x + y - z);
//8.67361737988404E-19


Result is not zero as expected. To use rational, you can download from here. Rational class is required BigInteger in SilverLight package. You can construct rational several ways.

Rational a = new Rational(1, 20);
Rational b = (Rational)1 / 15;
Rational c = 1m / 12m;
Console.WriteLine(a.Power(2) + b.Power(2) - c.Power(2));
//0


You can construct rational using new keyword, first argument is numerator, and second argument is denominator. Second method is to cast from integer. Last method is to guess from decimal. Please noted that guessing rational from decimal may lose accuracy, such as:

Rational r = 1000001m / 600001m;
Console.WriteLine(r.ToString());
//5/3


You can see that it keeps 5/3 instead of 1000001/600001. If you need accuracy, construct rational or casting from integer are better solutions.

The Rational class always keep rational in reduced form, such as:

Rational r = (Rational)5 / 10;
Console.WriteLine(r.ToString());
//1/2


It keeps 1/2 instead of 5/10. This will make all same proportions such as 1/2, 3/6, 5/10 are all equivalent.

This Rational class supports infinity, negative zero, and not a number (NaN). This will make all arithmetic operations are equal to real number, such as:

//1/0 makes infinity
Rational inf = (Rational)1 / 0;
Console.WriteLine(inf);
//Infinity

//Invert of negative zero makes negative infinity
Rational nzero = (Rational)0 / -1;
Console.WriteLine(1 / nzero);
//-Infinity

//infinity - infinity = nan
Rational nan = inf - inf;
Console.WriteLine(nan);
//NaN


Let's test rational with an easy question from projecteuler.net.
Find numerator of the fraction immediately to left of 3/7 with denominator <= 1000000

Rational r = (Rational)3 / 7;
r -= (Rational)1 / 999999;
Console.WriteLine(r.Numerator);
//428570


Next topic is to create continued fractions from square root and generate sequence of rational.

ไม่มีความคิดเห็น: