DonAman
Joined: 27 Nov 2011 Posts: 4
|
Posted: Thu Jan 26, 2012 7:43 am Post subject: Operator overloading |
|
|
Hi,
Here is a short tutorial about operator overloading in D. Simply put, it's an example of implementation of a class of rational numbers. The code contains basic examples of binary and unary operator overloading. Overloading comparison operators is quite simple in D, since one single method handles them all!
Code: | /*
rational.d
Implements rational numbers made of a numerator and a denominator, with some basic operations
Basic operations have to be overloaded, the same goes for comparison operators
*/
import std.stdio;
import std.string: format;
import std.math:abs;
class Rational {
private:
long _num;
ulong _den;
public:
this() {
_num = 0;
_den = 1;
}
this(long num,ulong den) {
if(den == 0) {
throw new Exception("trying to create a rational number with a denominator equal to zero.");
}
int n = gcd(num,den);
_num = num/n;
_den = den/n;
}
this(Rational d) {
_num = d._num;
_den = d._den;
}
static long min(long a,long b) {
return a<b ? a : b;
}
static long max(long a,long b) {
return a<b ? b: a;
}
static long gcd(long a,long b) {
if(a<0 || a<b || b<0) {
return gcd(max(abs(a),abs(b)),min(abs(a),abs(b)));
}
return (a%b!=0)? gcd(b,a%b) : b;
}
void display() {
(_den==1)?
writefln("%d",_num):
writefln("(" ~ format(_num) ~ "/" ~ format(_den) ~ ")");
}
Rational inverse() {
if(_num == 0) {
throw new Exception("0 is not invertible");
}
return (_num > 0) ?
new Rational(_den,_num):
new Rational(-(_den),-(_num));
}
static Rational maxr(ref Rational q1,ref Rational q2) {
return q1>q2? q1: q2; // ok because comparison operators are overloaded
}
/* Binary operator overloading */
Rational opAdd(Rational q) {
return new Rational(_num*q._den+_den*q._num,_den*q._den);
}
/* Adding floating numbers is slightly more difficult */
Rational opAdd(long d) {
return new Rational(_num+_den*d,_den);
}
Rational opMul(Rational q) {
return new Rational(_num*q._num,_den*q._den);
}
Rational opSub(Rational q) {
return new Rational(_num*q._den-_den*q._num,_den*q._den);
}
Rational opDiv(Rational q) {
if (q._num == 0) {
throw new Exception("trying to divide by a rational number equal to zero.");
}
return this*q.inverse();
}
void opAddAssign(Rational q) {
_num = (_num*q._den+_den*q._num);
_den = (_den*q._den);
/* conversion into an irreductible fraction */
ulong gcd = gcd((_num <0) ? (-_num) : (_num),_den);
if(gcd != 1) {
_num /= gcd;
_den /= gcd;
}
}
/* Unary operator overloading */
Rational opNeg() {
return new Rational(-(_num),_den);
}
/* Overloading comparison operators */
int opCmp(Rational other) {
return _num*other._den - other._num*_den;
}
}
void main() {
Rational r = new Rational();
writefln("Let's start with r = 0.");
r = r + 1;
writef("r = ");
r.display();
/* r = 1 */
r = r*new Rational(2,1);
writef("\t*2 = ");
r.display();
/* r = 2 */
r = (new Rational(1,3))*r;
writef("\t\t*1/3 = ");
r.display();
/* r = 2/3 */
r = r/(new Rational(3,1));
writef("\t\t\t/3 = ");
r.display();
/* r = 2/9 */
r = r + new Rational(1,3);
writef("\t\t\t\t+1/3 = ");
r.display();
/* r = 5/9 */
r += new Rational(1,3);
writef("r += 1/3 -> r = ");
r.display();
/* r = 8/9 */
r = r - new Rational(1,2);
writef("\t\t-1/2 = ");
r.display();
/* r = 7/18 */
r = -r;
writef("r = -r -> r = ");
r.display();
/* r = -7/18 */
Rational x = new Rational(-5,18);
r = Rational.maxr(r,x);
writef("max(r,-5/18) = ");
r.display();
/* r = -5/18 */
} |
(Compiled with dmd 1.071) |
|