2022秋-Java-03-面向对象1(基础、封装)——6-1 分数【函数题】
设计一个表示分数的类Fraction。这个类用两个int类型的变量分别表示分子和分母。注意,在创建和做完运算后应该化简分数为最简形式。如2/4应该被化简为1/2。
函数接口定义:
这个类的构造函数是:
Fraction(int a, int b)
- 构造一个a/b的分数。
这个类要提供以下的功能:
double toDouble();
- 将分数转换为double
Fraction plus(Fraction r);
- 将自己的分数和r的分数相加,产生一个新的Fraction的对象。
Fraction multiply(Fraction r);
- 将自己的分数和r的分数相乘,产生一个新的Fraction的对象。
String toString();
- 将自己以“分子/分母”的形式产生一个字符串。如果分数是1/1,应该输出
"1"
。当分子大于分母时,不需要提出整数部分,即"31/30"
是一个正确的输出。
裁判测试程序样例:
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
Fraction a = new Fraction(in.nextInt(), in.nextInt());
Fraction b = new Fraction(in.nextInt(), in.nextInt());
System.out.println(a);
System.out.println(b);
System.out.println(a.plus(b));
System.out.println(a.multiply(b).plus(new Fraction(5,6)));
System.out.println(a);
System.out.println(b);
System.out.println(a.toDouble());
in.close();
}
}
/* 请在这里填写答案 */
注意,你的类的定义应该这样开始:
class Fraction {
- 也就是说,在你的类的class前面不要有public。
输入样例:
2 4 1 3
输出样例:
1/2
1/3
5/6
1
1/2
1/3
0.5
解题代码如下:
class Fraction {
/**
* numer表示分数的分子 deno表示分数的分母
*/
private int numer;
private int deno;
Fraction(int a, int b) {
this.numer = a;
this.deno = b;
}
/**
* 转换成Double
*
* @return
*/
double toDouble() {
return this.numer*1.0/this.deno;
}
/**
* 求两个分数相加
*
* @param r
* @return
*/
Fraction plus(Fraction r) {
int newNumer = this.numer * r.getDeno() + r.getNumer() * this.deno;
int newDeno = this.deno * r.getDeno();
Fraction newFra = new Fraction(newNumer, newDeno);
return newFra;
}
Fraction multiply(Fraction r) {
Fraction newFra = new Fraction(this.numer * r.getNumer(), this.deno * r.getDeno());
return newFra;
}
// @Override
// public String toString() {
// int gcd = getGcd(this.numer, this.deno);
// this.numer /= gcd;
// this.deno /= gcd;
// if (this.deno==this.numer) {
// return "1";
// }else{
// if(this.numer*this.deno<0){
// return -1*Math.abs(this.numer) + "/" + Math.abs(this.deno);
// }else{
// return this.numer + "/" + this.deno;
// }
// }
// }
@Override
public String toString() {
int gcd = getGcd(Math.abs(this.numer), Math.abs(this.deno));
this.numer /= gcd;
this.deno /= gcd;
if(this.numer<0 && this.deno<0){
this.numer = -this.numer;
this.deno = -this.deno;
}
if (this.numer == this.deno) {
return "1";
} else {
return numer + "/" + deno;
}
}
/**
* 求两数最大公因数
*
* @param a
* @param b
* @return
*/
int getGcd(int a, int b) {
return b == 0 ? a:getGcd(b,a % b);
}
public int getNumer() {
return numer;
}
public void setNumer(int numer) {
this.numer = numer;
}
public int getDeno() {
return deno;
}
public void setDeno(int deno) {
this.deno = deno;
}
}
解题要点:
- 要学会求解gcd的算法。
- 本题要考虑输出是负数的情况,也就是要对输出的符号进行判断和控制。
- 本题对格式有特定的要求。尤其是toString处指出来的。
核心代码:
- 用递归方式写gcd:
/**
* 求两数最大公因数
*
* @param a
* @param b
* @return
*/
int getGcd(int a, int b) {
return b == 0 ? a:getGcd(b,a % b);
}
- 分数化简和输出格式控制:
- 方法一:
@Override
public String toString() {
int gcd = getGcd(Math.abs(this.numer), Math.abs(this.deno));
this.numer /= gcd;
this.deno /= gcd;
if(this.numer<0 && this.deno<0){
this.numer = -this.numer;
this.deno = -this.deno;
}
if (this.numer == this.deno) {
return "1";
} else {
return numer + "/" + deno;
}
}
-
gcd不考虑符号,特殊情况下的符号特殊考虑
-
方法二:
@Override
public String toString() {
int gcd = getGcd(this.numer, this.deno);
this.numer /= gcd;
this.deno /= gcd;
if (this.deno==this.numer) {
return "1";
}else{
if(this.numer*this.deno<0){
return -1*Math.abs(this.numer) + "/" + Math.abs(this.deno);
}else{
return this.numer + "/" + this.deno;
}
}
}
- 不去管gcd过程的符号
- 但是管漏掉的符号控制的可能情况
详细来说就是要额外考虑 分子分母单负的情况和分子分母双负 的情况。