分数是我们从小学就开始接触的一类有理数,但是在计算机中只有浮点型数据。我们今天(除夕)就来实现一个分数类,以见证这历史性的时刻。
从最基础的分数结构来思考,我们需要一个分子分母,比如这样:
public class Rational {
private int num; /* The numerator of this Rational */
private int den; /* The denominator of this Rational */
public Rational(int x, int y) {
num = x;
den = y;
}
}
我们一开始很容易这样写,但这样写是有很大问题的。例如算术运算规则对分子和分母的值有限制,这里面最明显的限制就是分母不能为0。构造器应该检查这种情况并在分母为0时抛出异常。还有,这样的分数不是最简形式,我们会有很多种不同的方式来表示同一个有理数。比如三分之一:
1/3 2/6 100/300 -1/-3 …
要处理这些问题,我们先遵循数学家们给的规则:
1.分数总是表示为最简形式,分子分母要同时处理它们的最大公约数。可以使用gcd方法求分子分母的最大公约数。
2.分母总是整数,也就是分数值是和分子一起存储的。
3.有理数0总是表示为分数0/1。
这样我们就比较容易地写出分数类的构造器了!当然,我们还可能需要传一个分母为1的假分数,这时直接把分子传给一个参数的构造器就行,我们用this关键字调用已经写好的构造器。
我们还要给分数器增加算术运算的方法以及通用的toString方法,所以代码的一种可能实现为:
public class Rational {
private int num;
private int den;
public Rational() {
this(0);
}
public Rational(int n) {
this(n, 1);
}
public Rational(int x, int y) {
if (y == 0) throw new RuntimeException("Division by zero");
if (x == 0) {
num = 0;
den = 1;
} else {
int g = gcd(Math.abs(x), Math.abs(y));
num = x / g;
den = Math.abs(y) / g;
if (y < 0) num = -num;
}
}
public Rational add(Rational r2) {
return new Rational(this.num * r2.den + r2.num * this.den, this.den * r2.den);
}
public Rational substract(Rational r2) {
return new Rational(this.num * r2.den - r2.num * this.den, this.den * r2.den);
}
public Rational multiply(Rational r2) {
return new Rational(this.num * r2.num, this.den * r2.den);
}
public Rational divide(Rational r2) {
return new Rational(this.num * r2.den, this.den * r2.num);
}
@Override
public String toString() {
if (den == 1)
return "" + num;
return num + "/" + den;
}
private int gcd(int x, int y) {
int r = x % y;
while (r != 0) {
x = y;
y = r;
r = x % y;
}
return y;
}
}
放爆竹的时光一去不复还,这个类设计地真好,不得不从书上借鉴过来!
版权声明:本文为Richard1997原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。