一个分数类的实现——Rational类

  • Post author:
  • Post category:其他


分数是我们从小学就开始接触的一类有理数,但是在计算机中只有浮点型数据。我们今天(除夕)就来实现一个分数类,以见证这历史性的时刻。

从最基础的分数结构来思考,我们需要一个分子分母,比如这样:

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 版权协议,转载请附上原文出处链接和本声明。