在编程中,数据类型基本会有数字类型,有的还会细分整数和小数,但是一般不会区分有理数与无理数。辣么,如何打造一个有理数类型呢?
什么是有理数类型?首先有理数就是分数。其次,有理数既然是一种数据结构,就有创建和操作的方法。
——————— 启发与 sicp ——————-
其实实现语言不重要,这里表达的是一种抽象分层的思想。(假装有)
java 实现:
package com.pycat.simple.ration;
import javafx.util.Pair;
/**
* Created by cat on 2018/6/10.
* 有理数
*/
public class Ration<K, V> extends Pair<K, V> {
/**
* Creates a new pair
*
* @param key The key for this pair
* @param value The value to use for this pair
*/
Ration(K key, V value) {
super(key, value);
}
@Override
public String toString() {
if (getValue() instanceof Integer) {
int v = (Integer) getValue();
return v == 1
? String.format("Ration(%s)", getKey())
: String.format("Ration(%s/%s)", getKey(), getValue());
} else if (getKey() == getValue()) {
return String.format("Ration(%s)", 1);
}
return String.format("Ration(%s/%s)", getKey(), getValue());
}
}
package com.pycat.simple.ration;
import com.pycat.simple.ration.Ration;
/**
* Created by cat on 2018/6/10.
* 有理数操作
*/
public class RationOperator {
private RationOperator() {
}
public static Ration<Integer, Integer> makeRation(int n, int d) {
if (d == 0) throw new ArithmeticException("denomination can't be zero.");
return new Ration<>(n / gcd(n, d), d / gcd(n, d));
}
public static int getNumber(Ration<Integer, Integer> ration) {
return ration.getKey();
}
public static int getDenominate(Ration<Integer, Integer> ration) {
return ration.getValue();
}
/**
* 有理数相加
*
* @param x ration
* @param y ration
* @return x + y (其中 x,y 都是有理数)
*/
public static Ration<Integer, Integer> add(Ration<Integer, Integer> x, Ration<Integer, Integer> y) {
int n = x.getKey() * y.getValue() + x.getValue() * y.getKey();
int d = x.getValue() * y.getValue();
return makeRation(n, d);
}
/**
* 有理数相减
*
* @param x ration
* @param y ration
* @return x - y (其中 x,y 都是有理数)
*/
public static Ration<Integer, Integer> minus(Ration<Integer, Integer> x, Ration<Integer, Integer> y) {
int n = x.getKey() * y.getValue() - x.getValue() * y.getKey();
int d = x.getValue() * y.getValue();
return makeRation(n, d);
}
/**
* 有理数相乘
*
* @param x ration
* @param y ration
* @return x * y (其中 x,y 都是有理数)
*/
public static Ration<Integer, Integer> multi(Ration<Integer, Integer> x, Ration<Integer, Integer> y) {
int n = x.getKey() * y.getKey();
int d = x.getValue() * y.getValue();
return makeRation(n, d);
}
/**
* 有理数相除
*
* @param x ration
* @param y ration
* @return x / y (其中 x,y 都是有理数)
*/
public static Ration<Integer, Integer> divide(Ration<Integer, Integer> x, Ration<Integer, Integer> y) {
return multi(x, makeRation(y.getValue(), y.getKey()));
}
/**
*
* 第一步:任意给定两个正整数;判断它们是否都是偶数。若是,则用2约简;若不是则执行第二步。
* 第二步:以较大的数减较小的数,接着把所得的差与较小的数比较,并以大数减小数。继续这个操作,直到所得的减数和差相等为止。
* 则第一步中约掉的若干个2与第二步中等数的乘积就是所求的最大公约数。
* 其中所说的“等数”,就是最大公约数。求“等数”的办法是“更相减损”法。所以更相减损法也叫等值算法。
*
* @param n
* @param d
* @return
*/
private static int gcd(int n, int d) {
int before = 1;
while (n % 2 == 0 && d % 2 == 0) {
n = n / 2;
d = d / 2;
before *= 2;
}
int r = 0;
int max;
int min;
max = Math.max(n, d);
min = Math.min(n, d);
n = max;
d = min;
while (r != d) {
r = n - d;
n = Math.max(r, d);
d = Math.min(r, d);
max = Math.max(n, d);
min = Math.min(n, d);
n = max;
d = min;
}
return r * before;
}
public static void main(String[] args) {
// System.out.println(gcd(6, 8));
Ration<Integer, Integer> a = RationOperator.makeRation(1, 2);
Ration<Integer, Integer> b = RationOperator.makeRation(1, 4);
System.out.println(String.format("%s + %s = %s", a, b, RationOperator.add(a, b)));
System.out.println(String.format("%s - %s = %s", a, b, RationOperator.minus(a, b)));
System.out.println(String.format("%s * %s = %s", a, b, RationOperator.multi(a, b)));
System.out.println(String.format("%s / %s = %s", a, b, RationOperator.divide(a, b)));
}
}