Java实现分数
- Java实现分数 推荐度:
- 相关推荐
Java实现分数
自己独立实现的,如果有bug或者错误,欢迎评论区留言!
文章目录
- 文档
- 代码
文档
字段摘要:
修饰符 | 字段 | 解释 |
---|---|---|
static final Fraction | ONE | 分数:1,分子、分母都是1的分数 |
static final Fraction | ZERO | 分数:0,分子是0、分母是1的分数 |
构造方法摘要 :
构造方法 | 解释 |
---|---|
Fraction(String fractionStr) | 根据字符串生成一个分数,支持识别”/"、小数点 |
Fraction(double numerator) | 根据一个double数生成一个分数 |
Fraction(long numerator) | 根据一个整型数字生成一个分数;分子式该数字,分母是1 |
Fraction(long numerator, long denominator) | 根据提供的分子、分母生成分数;numerator:分子,denominator:分母 |
方法摘要 :
修饰符 | 方法 | 解释 |
---|---|---|
int | intValue() | 返回对应分数的int值 |
long | longValue() | 返回对应分数的long 值 |
float | floatValue() | 返回对应分数的float 值 |
double | doubleValue() | 返回对应分数的double 值 |
int | compareTo(Fraction o) | 和另一个分数比大小 |
String | toString() | 以假分数形式返回分数,使用”/“作为分号 |
Fraction | add(Fraction fraction) | 返回两个分数的和,不会改编原分数 |
Fraction | sub(Fraction fraction) | 返回两个分数的差,不会改编原分数 |
Fraction | mul(Fraction fraction) | 返回两个分数的积,不会改编原分数 |
Fraction | div(Fraction fraction) | 返回两个分数的商,不会改编原分数 |
Fraction | clone() | 返回一个克隆对象,深拷贝 |
Fraction | getOppositeNumber(Fraction fraction) | 返回参数的相反数,a的相反数是-a |
Fraction | getReciprocal(Fraction fraction) | 返回参数的倒数,a的倒数是1/a |
boolean | isZero() | 判断该分数是否为0 |
long | getNumerator() | 获取分子 |
long | getDenominator() | 获取分母 |
void | setNumerator(long numerator) | 设置新的分子 |
void | setDenominator(long denominator) | 设置新的分母 |
代码
/*** @description: 分数* @author: liangjiayy* @create: 2022-09-30 23:31**/
public class Fraction extends Number implements Comparable<Fraction>, Operationable<Fraction> {/*** 1*/public static final Fraction ONE = new Fraction(1);/*** 0*/public static final Fraction ZERO = new Fraction(0);/*** 分子*/private long numerator;/*** 分母*/private long denominator;public Fraction(String fractionStr) {String[] split = fractionStr.trim().split("/");if (split.length > 2 || split.length == 0) {throw new RuntimeException("将\"" + fractionStr + "\"转化为分数出现了异常!");}Fraction num, den;//分子if (split[0].contains(".")) {num = convertDouble2fraction(Double.parseDouble(split[0]));} else {num = new Fraction(Long.parseLong(split[0]));}//分母if (split.length == 2) {if (split[1].contains(".")) {den = convertDouble2fraction(Double.parseDouble(split[1]));} else {den = new Fraction(Long.parseLong(split[1]));}} else {this.numerator = num.numerator;this.denominator = num.denominator;return;}Fraction div = num.div(den);this.numerator = div.numerator;this.denominator = div.denominator;}public Fraction(double numerator) {Fraction fraction = convertDouble2fraction(numerator);this.numerator = fraction.numerator;this.denominator = fraction.denominator;}private Fraction convertDouble2fraction(double numerator) {String[] split = (numerator + "").split("\\.");//整数部分long left = Long.parseLong(split[0]);//小数部分long right = Long.parseLong(split[1]);int len = split[1].length();long pow = (long) Math.pow(10, len);return new Fraction(left * pow + right, pow);}public Fraction(long numerator) {this(numerator, 1L);}public Fraction(long numerator, long denominator) {this.numerator = numerator;this.denominator = denominator;}/*** Returns the value of the specified number as an {@code int},* which may involve rounding or truncation.** @return the numeric value represented by this object after conversion* to type {@code int}.*/@Overridepublic int intValue() {return (int) (numerator / denominator);}/*** Returns the value of the specified number as a {@code long},* which may involve rounding or truncation.** @return the numeric value represented by this object after conversion* to type {@code long}.*/@Overridepublic long longValue() {return numerator / denominator;}/*** Returns the value of the specified number as a {@code float},* which may involve rounding.** @return the numeric value represented by this object after conversion* to type {@code float}.*/@Overridepublic float floatValue() {return (float) (1.0 * numerator / denominator);}/*** Returns the value of the specified number as a {@code double},* which may involve rounding.** @return the numeric value represented by this object after conversion* to type {@code double}.*/@Overridepublic double doubleValue() {return 1.0 * numerator / denominator;}/*** Compares this object with the specified object for order. Returns a* negative integer, zero, or a positive integer as this object is less* than, equal to, or greater than the specified object.** <p>The implementor must ensure <tt>sgn(xpareTo(y)) ==* -sgn(ypareTo(x))</tt> for all <tt>x</tt> and <tt>y</tt>. (This* implies that <tt>xpareTo(y)</tt> must throw an exception iff* <tt>ypareTo(x)</tt> throws an exception.)** <p>The implementor must also ensure that the relation is transitive:* <tt>(xpareTo(y)>0 && ypareTo(z)>0)</tt> implies* <tt>xpareTo(z)>0</tt>.** <p>Finally, the implementor must ensure that <tt>xpareTo(y)==0</tt>* implies that <tt>sgn(xpareTo(z)) == sgn(ypareTo(z))</tt>, for* all <tt>z</tt>.** <p>It is strongly recommended, but <i>not</i> strictly required that* <tt>(xpareTo(y)==0) == (x.equals(y))</tt>. Generally speaking, any* class that implements the <tt>Comparable</tt> interface and violates* this condition should clearly indicate this fact. The recommended* language is "Note: this class has a natural ordering that is* inconsistent with equals."** <p>In the foregoing description, the notation* <tt>sgn(</tt><i>expression</i><tt>)</tt> designates the mathematical* <i>signum</i> function, which is defined to return one of <tt>-1</tt>,* <tt>0</tt>, or <tt>1</tt> according to whether the value of* <i>expression</i> is negative, zero or positive.** @param o the object to be compared.* @return a negative integer, zero, or a positive integer as this object* is less than, equal to, or greater than the specified object.* @throws NullPointerException if the specified object is null* @throws ClassCastException if the specified object's type prevents it* from being compared to this object.*/@Overridepublic int compareTo(Fraction o) {Fraction[] fractions = convert2sameDenominator(this, o);//如果分母是正数,比较分子if (fractions[0].denominator > 0) {return Longpare(fractions[0].numerator, fractions[1].numerator);}return -Longpare(fractions[0].numerator, fractions[1].numerator);}/*** 通分,将两个分数转化成同分母分数** @param f1* @param f2* @return Fraction[0]:第一个分数转化后的结果,Fraction[1]:第二个分母转化后的结果*/private Fraction[] convert2sameDenominator(Fraction f1, Fraction f2) {//找公倍数long leastCommonMultiple = findLeastCommonMultiple(f1.denominator, f2.denominator);Fraction[] res = new Fraction[2];//转化为指定的分母res[0] = convertDenominator(f1, leastCommonMultiple);res[1] = convertDenominator(f2, leastCommonMultiple);return res;}/*** 将分数的分母转化为指定的值* 注意:新的分母必须是旧的分母的倍数** @param fraction* @param denominator 新的分母* @return*/private Fraction convertDenominator(Fraction fraction, long denominator) {if (denominator % fraction.denominator != 0) {throw new RuntimeException("无法将\"" + fraction + "\"转化为分母为" + denominator + "的分数!");}return new Fraction(fraction.numerator * (denominator / fraction.denominator), denominator);}/*** 找最小公倍数** @param num1* @param num2* @return*/private long findLeastCommonMultiple(long num1, long num2) {//找公因数long greatestCommonDivisor = findGreatestCommonDivisor(num1, num2);//公倍数return num1 * num2 / greatestCommonDivisor;}/*** 找最大公因数** @param num1* @param num2* @return*/private long findGreatestCommonDivisor(long num1, long num2) {//辗转相除法long tmp;while (num2 != 0) {tmp = num1 % num2;num1 = num2;num2 = tmp;}return num1;}@Overridepublic String toString() {Fraction fraction = convert2theSimplestFraction(this);this.numerator = fraction.numerator;this.denominator = fraction.denominator;//分母等于1,只返回分子if (denominator == 1) {return numerator + "";}if (numerator == 0) {return 0 + "";}return numerator + "/" + denominator;}/*** 加法** @param fraction* @return*/@Overridepublic Fraction add(Fraction fraction) {//通分Fraction[] fractions = convert2sameDenominator(this, fraction);//分子相加Fraction res = new Fraction(fractions[0].numerator + fractions[1].numerator, fractions[0].denominator);//化简为最简带分数return convert2theSimplestFraction(res);}/*** Creates and returns a copy of this object. The precise meaning* of "copy" may depend on the class of the object. The general* intent is that, for any object {@code x}, the expression:* <blockquote>* <pre>* x.clone() != x</pre></blockquote>* will be true, and that the expression:* <blockquote>* <pre>* x.clone().getClass() == x.getClass()</pre></blockquote>* will be {@code true}, but these are not absolute requirements.* While it is typically the case that:* <blockquote>* <pre>* x.clone().equals(x)</pre></blockquote>* will be {@code true}, this is not an absolute requirement.* <p>* By convention, the returned object should be obtained by calling* {@code super.clone}. If a class and all of its superclasses (except* {@code Object}) obey this convention, it will be the case that* {@code x.clone().getClass() == x.getClass()}.* <p>* By convention, the object returned by this method should be independent* of this object (which is being cloned). To achieve this independence,* it may be necessary to modify one or more fields of the object returned* by {@code super.clone} before returning it. Typically, this means* copying any mutable objects that comprise the internal "deep structure"* of the object being cloned and replacing the references to these* objects with references to the copies. If a class contains only* primitive fields or references to immutable objects, then it is usually* the case that no fields in the object returned by {@code super.clone}* need to be modified.* <p>* The method {@code clone} for class {@code Object} performs a* specific cloning operation. First, if the class of this object does* not implement the interface {@code Cloneable}, then a* {@code CloneNotSupportedException} is thrown. Note that all arrays* are considered to implement the interface {@code Cloneable} and that* the return type of the {@code clone} method of an array type {@code T[]}* is {@code T[]} where T is any reference or primitive type.* Otherwise, this method creates a new instance of the class of this* object and initializes all its fields with exactly the contents of* the corresponding fields of this object, as if by assignment; the* contents of the fields are not themselves cloned. Thus, this method* performs a "shallow copy" of this object, not a "deep copy" operation.* <p>* The class {@code Object} does not itself implement the interface* {@code Cloneable}, so calling the {@code clone} method on an object* whose class is {@code Object} will result in throwing an* exception at run time.** @return a clone of this instance.* @throws CloneNotSupportedException if the object's class does not* support the {@code Cloneable} interface. Subclasses* that override the {@code clone} method can also* throw this exception to indicate that an instance cannot* be cloned.* @see Cloneable*/@Overrideprotected Fraction clone() {return new Fraction(this.numerator, this.denominator);}/*** 约分** @param fraction* @return*/private Fraction convert2theSimplestFraction(Fraction fraction) {long leastCommonMultiple = findGreatestCommonDivisor(fraction.numerator, fraction.denominator);if (leastCommonMultiple == 1) {return fraction.clone();}//分子分母,同时除以最大公约数return new Fraction(fraction.numerator / leastCommonMultiple, fraction.denominator / leastCommonMultiple);}/*** 减法** @param fraction* @return*/@Overridepublic Fraction sub(Fraction fraction) {// 相反数fraction = getOppositeNumber(fraction);return add(fraction);}/*** 相反数** @param fraction* @return*/@Overridepublic Fraction getOppositeNumber(Fraction fraction) {return new Fraction(-fraction.numerator, fraction.denominator);}/*** 乘法** @param fraction* @return*/@Overridepublic Fraction mul(Fraction fraction) {Fraction res = new Fraction(numerator * fraction.numerator, denominator * fraction.denominator);return convert2theSimplestFraction(res);}/*** 除法** @param fraction* @return*/@Overridepublic Fraction div(Fraction fraction) {fraction = getReciprocal(fraction);return mul(fraction);}/*** 倒数** @param fraction* @return*/@Overridepublic Fraction getReciprocal(Fraction fraction) {return new Fraction(fraction.denominator, fraction.numerator);}public boolean isZero() {return this.numerator == 0;}/*** 分子** @return*/public long getNumerator() {return numerator;}/*** 分母** @return*/public long getDenominator() {return denominator;}public void setNumerator(long numerator) {this.numerator = numerator;}public void setDenominator(long denominator) {this.denominator = denominator;}
}/*** 支持运算的,包括加、减、乘、除*/
interface Operationable<T> {/*** 加法** @param t* @return*/T add(T t);/*** 减法** @param t* @return*/T sub(T t);/*** 乘法** @param t* @return*/T mul(T t);/*** 除法** @param t* @return*/T div(T t);/*** 相反数** @param fraction* @return*/Fraction getOppositeNumber(Fraction fraction);/*** 倒数** @param fraction* @return*/Fraction getReciprocal(Fraction fraction);
}