声明:这并不是一个完美的代码,过掉yhh没有问题,但是wjx的学生慎重选择,你可能在答辩的时候被狠狠背刺。
实验要求:
- 掌握类、对象、类成员变量、对象成员方法、对象的构造方法、类静态变量和类静态方法。
- 掌握数组的使用、掌握访问权限。
- 掌握Object类的重要方法,包括toString() 和 clone() 方法。
- 实验实现目标:实现分数类及其运算,能够实现任意的分数的单次的和批量的正确、高效的运算。
实验内容:
1.实验背景介绍
(1)分数是指两个整数的比。分数本身可以构造和约分;任何整数都可以看作一个分数。
(2)单个分数可以运算,包括求倒数、求相反数、扩大、缩小等。
(3)两个分数可以运算,包括加减乘除等。
2.用记事本书写一个Java程序
(1)、建立个人子目录
步骤1:建立个人子目录
第一次上机时先在D盘上建立一个以自己学号+姓名为目录名的子目录,如学号为210824109的张三同学,就用“210824109张三”为子目录名。实验完成的源代码、Java字节码和实验报告三个文件都要放在这个文件夹下(称为上交文件夹)。
步骤2:建立Java源代码文件
在所建立的文件夹下建立一个记事本文件Fraction.txt,并把它重命名为Fraction.java
(2)、编写源代码
步骤1:创建一个公共类Fraction
要创建的公共类在默认包中,可引入其它的包。所创建的公共类在文件中的一行如下:
public class Fraction{… …}
步骤2:建立主方法main( )
在类Fraction的类体中编写主方法:
public static void main(String[] args){… …}
步骤3:编写方法和Fraction的主方法main( )
主方法用于测试。辅助方法的方法头请参见附件
3.调试和运行
(1)、调试
步骤1:使用命令行工具,先进入用所建的目录下。参见图1。
步骤2:用javac Fraction.java编译并调试源代码文件。参见图1。
(2)、运行
使用java Fraction运行程序。参见图1。
运行说明:第一次,让main()方法调用测试方法testSimple(),然后编译运行;第二次,让main()方法调用测试方法testComplex(),然后编译运行。
/*package bjfuwjx_exp1;*/
import javax.print.attribute.standard.PrinterName;
import java.math.BigInteger;
import java.util.PrimitiveIterator;
/**
* 此类Fractional是一个用于分数表示和运算的类。
* 该类基于大整数类BigInteger。
*/
public class Fraction implements Comparable<Fraction>{
private int sign = 0; // 分数的正负号,正数1,负数-1,零0
private BigInteger numerator = BigInteger.ZERO; // 分数的分子
private BigInteger denominator = BigInteger.ZERO; // 分数的分母
public static final Fraction ZERO = new Fraction(0, 1); // 分数常量 0/1
public static final Fraction ONE = new Fraction(1, 1); // 分数常量 +1/1
public static final Fraction NEGATIVE_INFINITY = new Fraction(-1, 0); // 分数常量 -1/0,即负无穷
public static final Fraction POSITIVE_INFINITY = new Fraction(1, 0); // 分数常量 +1/0,即正无穷
public static final Fraction NAN = new Fraction(0, 0); // 分数常量,0/0,即:不是一个分数
/**
* 构造方法:由两个大整数构造一个分数,大整数带正负号,最终的分数的正负号通过计算获得。
* 需要进行处理,包括符号处理,也包括约分处理。
* @param primNumerator 输入的分子,最终的构造的分数的分子很可能不是这个输入。
* @param primDenominator 输入的分母,最终的构造的分数的分母很有可能不是这个输入。
*/
public Fraction(BigInteger primNumerator, BigInteger primDenominator) {
// Add your code here
BigInteger Zero = BigInteger.valueOf(0);// 0
BigInteger One = BigInteger.valueOf(1);// 1
if(primNumerator.equals(Zero) && primDenominator.equals(Zero))// 0/0
{
this.sign = 0;
this.numerator = Zero;
this.denominator = Zero;
}
else if(primNumerator.equals(Zero) && primDenominator.equals(One)) // 0/1
{
this.sign = primDenominator.divide(primDenominator.abs()).intValue();
this.numerator = Zero;
this.denominator = One;
}
else if(primNumerator.equals(One) && primDenominator.equals(Zero))// 1/0
{
this.sign = primNumerator.divide(primNumerator.abs()).intValue();
this.numerator = One;
this.denominator = Zero;
}
else
{
if( (primNumerator.compareTo(Zero)==1 && primDenominator.compareTo(Zero)==1) || (primNumerator.compareTo(Zero)==-1 && primDenominator.compareTo(Zero)==-1))
this.sign = 1;
else if((primNumerator.compareTo(Zero)==-1 && primDenominator.compareTo(Zero)==1) || (primNumerator.compareTo(Zero)==1 && primDenominator.compareTo(Zero)==-1))
this.sign = -1;
else
this.sign = 0;
BigInteger max_all = primNumerator.gcd(primDenominator);
this.numerator = primNumerator.divide(max_all).abs();
this.denominator = primDenominator.divide(max_all).abs();
}
}
/**
* 用两个长整型构造一个分数。
* @param lNumerator 输入的长整数分子。
* @param lDenominator 输入的长整数分母。
*/
public Fraction(long lNumerator, long lDenominator) {
// Add your code here
BigInteger Zero = BigInteger.valueOf(0);// 0
BigInteger One = BigInteger.valueOf(1);// 1
BigInteger primNumerator = BigInteger.valueOf(lNumerator);
BigInteger primDenominator = BigInteger.valueOf(lDenominator);
if(primNumerator.equals(Zero) && primDenominator.equals(Zero))// 0/0
{
this.sign = 0;
this.numerator = Zero;
this.denominator = Zero;
}
else if(primNumerator.equals(Zero) && primDenominator.equals(One)) // 0/1
{
this.sign = primDenominator.divide(primDenominator.abs()).intValue();
this.numerator = Zero;
this.denominator = One;
}
else if(primNumerator.equals(One) && primDenominator.equals(Zero))// 1/0
{
this.sign = primNumerator.divide(primNumerator.abs()).intValue();
this.numerator = One;
this.denominator = Zero;
}
else
{
if( (primNumerator.compareTo(Zero)==1 && primDenominator.compareTo(Zero)==1) || (primNumerator.compareTo(Zero)==-1 && primDenominator.compareTo(Zero)==-1))
this.sign = 1;
else if((primNumerator.compareTo(Zero)==-1 && primDenominator.compareTo(Zero)==1) || (primNumerator.compareTo(Zero)==1 && primDenominator.compareTo(Zero)==-1))
this.sign = -1;
else
this.sign = 0;
BigInteger max_all = primNumerator.gcd(primDenominator);
this.numerator = primNumerator.divide(max_all).abs();
this.denominator = primDenominator.divide(max_all).abs();
}
}
/**
* 获取本分数的正负号,用-1、0、1表示。
* @return 本分数的正负号。
*/
public int getSign() {
// Add your code here
return this.sign;
}
/**
* 获取本分数的分子,注意分子恒为非负。
* @return 本分数的分子。
*/
public BigInteger getNumerator() {
// Add your code here
return this.numerator.abs();
}
/**
* 获取本分数的分母。注意分母恒为非负。
* @return 本分数的分母。
*/
public BigInteger getDenominator() {
// Add your code here
return this.denominator.abs();
}
/**
* 用一个长整数构造一个分数,默认分数的分母是1。
* @param integerValue 输入的长整数,其绝对值与构造生成的分数的分子相同。
*/
public Fraction(long integerValue) {
// Add your code here;
BigInteger Zero = BigInteger.valueOf(0);// 0
BigInteger One = BigInteger.valueOf(1);// 1
BigInteger primNumerator = BigInteger.valueOf(integerValue);//long -> BigInt
BigInteger primDenominator = One;
if(primNumerator.equals(Zero) && primDenominator.equals(Zero))// 0/0
{
this.sign = 0;
this.numerator = Zero;
this.denominator = Zero;
}
else if(primNumerator.equals(Zero) && primDenominator.equals(One)) // 0/1
{
this.sign = primDenominator.divide(primDenominator.abs()).intValue();
this.numerator = Zero;
this.denominator = One;
}
else if(primNumerator.equals(One) && primDenominator.equals(Zero))// 1/0
{
this.sign = primNumerator.divide(primNumerator.abs()).intValue();
this.numerator = One;
this.denominator = Zero;
}
else
{
if( (primNumerator.compareTo(Zero)==1 && primDenominator.compareTo(Zero)==1) || (primNumerator.compareTo(Zero)==-1 && primDenominator.compareTo(Zero)==-1))
this.sign = 1;
else if((primNumerator.compareTo(Zero)==-1 && primDenominator.compareTo(Zero)==1) || (primNumerator.compareTo(Zero)==1 && primDenominator.compareTo(Zero)==-1))
this.sign = -1;
else
this.sign = 0;
BigInteger max_all = primNumerator.gcd(primDenominator);
this.numerator = primNumerator.divide(max_all).abs();
this.denominator = primDenominator.divide(max_all).abs();
}
}
/**
* 用来描述这个分数的字符串,例如“-7/2”,“+1/0”等等。
* @return
*/
@Override
public String toString() {
// Add your code here
String s = " ";
if(this.sign==1)
s = "+";
else if(this.sign==-1)
s = "-";
s += this.numerator.toString();
s += "/";
s += this.denominator.toString();
return s;
}
/**
* 判断此分数是否为“非数”,也就是是否是“0/0”类型。
* @return 如果是一个非数,返回true,否则返回false
*/
public boolean isNaN() {
// Add your code here
BigInteger Zero = BigInteger.valueOf(0);
if(this.numerator.equals(Zero) && this.denominator.equals(Zero))
return true;
else return false;
}
/**
* 判断此分数是否为0,也就是是否为“0/1”这各类型的分数。
* @return 是的话返回true;否则返回false
*/
public boolean isZero() {
// Add your code here
BigInteger Zero = BigInteger.valueOf(0);
BigInteger One = BigInteger.valueOf(1);
if(this.numerator.equals(Zero) && this.denominator.equals(One))
return true;
else return false;
}
/**
* 判断此分数是否是正的分数;当然,正无穷也是正的分数。
* @return 是的话返回true,否则返回false。
*/
public boolean isPositive() {
// Add your code here
if(this.sign==1) return true;
else return false;
}
/**
* 判断此分数是否为负的,当然负无穷也是负的。
* @return 如果是负分数,则返回true,否则返回false。
*/
public boolean isNegative() {
// Add your code here
if(this.sign==-1) return true;
else return false;
}
/**
* 判断此分数是否为无穷大,包括正无穷和负无穷。
* @return 如果是无穷大,则返回true,否则返回false。
*/
public boolean isInfinite() {
// Add your code here
BigInteger Zero = BigInteger.valueOf(0);
if(!this.numerator.equals(Zero) && this.denominator.equals(Zero))
return true;
else return false;
}
/**
* 把本分数的内容全部拷贝,生成一个新的分数返回。
* @return 本分数的一个复制版本。
*/
@Override
public Fraction clone() {
// Add your code here
BigInteger max_all = this.numerator.gcd(this.denominator);
BigInteger clone_Nnumerator = this.numerator.divide(max_all);
BigInteger clone_Denominator = this.denominator.divide(max_all);
Fraction clone_number = new Fraction(clone_Nnumerator,clone_Denominator);
clone_number.sign = this.sign;
return clone_number;
}
/**
* 求本分数的绝对值并返回。
* @return 本分数的绝对值,也是一个分数。
*/
public Fraction abs() {
// Add your code here
Fraction abs_number = new Fraction(this.numerator.abs(),this.denominator.abs());
abs_number.sign = this.sign;
return abs_number;
}
/**
* 求本分数的相反数,也是一个分数。
* @return 本分数的相反数。
*/
public Fraction opposite() {
// Add your code here
Fraction op_number = new Fraction(this.numerator,this.denominator);
op_number.sign = this.sign * -1;
return op_number;
}
/**
* 求本分数的倒数,也是一个分数。正负无穷的倒数都是0,但0的倒数规定为正无穷而不是负无穷。
* @return 本分数的倒数。
*/
public Fraction reciprocal() {
// Add your code here
Fraction rec_number = new Fraction(this.denominator, this.numerator);
rec_number.sign = this.sign;
return rec_number;
}
/**
* 绝对值比较大小。本分数的绝对值和that的绝对值比较大小。
* 把NaN当作0处理;正无穷和正无穷比较为相等。
* @param that 与本分数待比较的分数。
* @return 当本分数的绝对值和that的绝对值相等时返回0;本分数绝对值小的时候返回-1,绝对值大的时候返回1。
*/
private int absCompareTo(Fraction that) {
// Add your code here
BigInteger Zero = BigInteger.valueOf(0);
BigInteger mul1 = this.numerator.multiply(that.denominator);
BigInteger mul2 = this.denominator.multiply(that.numerator);
BigInteger N = mul1.subtract(mul2);
BigInteger D = this.denominator.multiply(that.denominator);
BigInteger sub = N.divide(D);
if(sub.compareTo(Zero) == 0)
return 0;
else if(sub.compareTo(Zero) == 1)
return 1;
else return -1;
}
/**
* 两个分数比较大小。
* @param that 与本分数待比较的分数。
* @return 如果两个分数值相等,返回0;如果本分数小,返回-1;否则返回1。
*/
@Override
public int compareTo(Fraction that) {
// Add your code here
BigInteger Zero = BigInteger.valueOf(0);
BigInteger mul1 = this.numerator.multiply(that.denominator);
BigInteger mul2 = this.denominator.multiply(that.numerator);
BigInteger D = this.denominator.multiply(that.denominator);
BigInteger N = Zero;
BigInteger sub = Zero;
if(this.sign * that.sign > 0)
{
N = mul1.subtract(mul2);
sub = N.divide(D);
if(this.sign > 0)
{
if(sub.compareTo(Zero) == 0)
return 0;
else if(sub.compareTo(Zero) == 1)
return 1;
else return -1;
}
else
{
if(sub.compareTo(Zero) == 0)
return 0;
else if(sub.compareTo(Zero) == 1)
return -1;
else return 1;
}
}
else if(this.sign * that.sign < 0)
{
if(this.sign > 0)
return 1;
else return -1;
}
else
{
if(this.sign==0)
{
if(that.sign<0)
return 1;
else if(that.sign==0)
return 0;
else return 1;
}
else
{
if(this.sign<0)
return 1;
else if(this.sign==0)
return 0;
else return 1;
}
}
}
/**
* 两个非负分数相加。
* @param that 与本分数待相加的分数。
* @return 两个分数相加的和,仍然时一个分数。
*/
private Fraction positiveAdd(Fraction that) {
// Add your code here
BigInteger mul1 = this.numerator.multiply(that.denominator);
BigInteger mul2 = this.denominator.multiply(that.numerator);
BigInteger N = mul1.add(mul2);
BigInteger D = this.denominator.multiply(that.denominator);
Fraction add = new Fraction(N, D);
return add;
}
/**
* 两个非负的分数相减。
* @param smaller 这是减数,本分数时被减数。
* @return 返回两个分数的差。
*/
private Fraction positiveSubtract(Fraction smaller) {
// Add your code here
BigInteger mul1 = this.numerator.multiply(smaller.denominator);
BigInteger mul2 = this.denominator.multiply(smaller.numerator);
BigInteger N = mul1.subtract(mul2);
BigInteger D = this.denominator.multiply(smaller.denominator);
Fraction Subtract = new Fraction(N, D);
return Subtract;
}
/**
* 两个分数相加。
* @param that 加数。本分数是被加数。
* @return 两个分数的加和。
*/
public Fraction add(Fraction that) {
// Add your code here
BigInteger Zero = BigInteger.valueOf(0);
BigInteger mul1 = this.numerator.multiply(that.denominator);
BigInteger mul2 = this.denominator.multiply(that.numerator);
BigInteger D = this.denominator.multiply(that.denominator);
BigInteger N = Zero;
if(this.sign > 0 && that.sign < 0)
N = mul1.subtract(mul2);
else if(this.sign > 0 && that.sign > 0)
N = mul1.add(mul2);
else if(this.sign < 0 && that.sign > 0)
N = mul2.subtract(mul1);
else
N = mul1.add(mul2).negate();
Fraction add = new Fraction(N,D);
return add;
}
/**
* 两个分数相减。
* @param that 减数。
* @return 本分数减去that的差。
*/
public Fraction subtract(Fraction that) {
// Add your code here;
BigInteger Zero = BigInteger.valueOf(0);
BigInteger mul1 = this.numerator.multiply(that.denominator);
BigInteger mul2 = this.denominator.multiply(that.numerator);
BigInteger D = this.denominator.multiply(that.denominator);
BigInteger N = Zero;
if(this.sign > 0 && that.sign < 0)
N = mul1.add(mul2);
else if(this.sign > 0 && that.sign > 0)
N = mul1.subtract(mul2);
else if(this.sign < 0 && that.sign > 0)
{
N = mul1.add(mul2);
N = N.negate();
}
else
N = mul2.subtract(mul1);
Fraction subtract = new Fraction(N,D);
return subtract;
}
/**
* 一个分数和另一个分数相乘。
* @param factor 乘数。本分数是被乘数。
* @return 两个分数的积,仍然是一个分数。
*/
public Fraction multiply(Fraction factor) {
// Add your code here
BigInteger mulN = this.numerator.multiply(factor.numerator);
BigInteger mulD = this.denominator.multiply(factor.denominator);
BigInteger max_all = mulN.gcd(mulD);
mulD = mulD.divide(max_all);
mulN = mulN.divide(max_all);
if(this.sign * factor.sign < 0)
mulN.negate();
Fraction mult = new Fraction(mulN,mulD);
return mult;
}
/**
* 本分数乘以一个长整数因子,获取一个新的分数。
* @param ratio 待乘的因子。
* @return 放大后新的分数。
*/
public Fraction multiply(long ratio) {
// Add your code here
Fraction factor = new Fraction(ratio);
BigInteger mulN = this.numerator.multiply(factor.numerator);
BigInteger mulD = this.denominator.multiply(factor.denominator);
BigInteger max_all = mulN.gcd(mulD);
mulD = mulD.divide(max_all);
mulN = mulN.divide(max_all);
if(this.sign * factor.sign < 0)
mulN.negate();
Fraction mult = new Fraction(mulN,mulD);
return mult;
}
/**
* 获取本分数除以另外一个分数的商。
* @param divisor 除数。
* @return 商。
*/
public Fraction divide(Fraction divisor) {
// Add your code here
BigInteger mulN = this.numerator.multiply(divisor.denominator);
BigInteger mulD = this.denominator.multiply(divisor.numerator);
BigInteger max_all = mulN.gcd(mulD);
mulD = mulD.divide(max_all);
mulN = mulN.divide(max_all);
if(this.sign * divisor.sign < 0)
mulN.negate();
Fraction divide = new Fraction(mulN,mulD);
return divide;
}
/**
* 获取本分数除以一个长整数因子后的商。
* @param ratio 除数,一个长整数因子。
* @return 商。
*/
public Fraction divide(long ratio) {
// Add your code here
Fraction divisor = new Fraction(ratio);
BigInteger mulN = this.numerator.multiply(divisor.denominator);
BigInteger mulD = this.denominator.multiply(divisor.numerator);
BigInteger max_all = mulN.gcd(mulD);
mulD = mulD.divide(max_all);
mulN = mulN.divide(max_all);
if(this.sign * divisor.sign < 0)
mulN.negate();
Fraction divide = new Fraction(mulN,mulD);
return divide;
}
/**
* 一个简单的测试。计算 1/(1*2) + 1/(2*3) + ... + 1/(100*101)
* 事实上,上式等于 (1/1 - 1/2) + (1/2 - 1/3) + ... + (1/100 - 1/101)
* 最后的结果应该是 "+100/101"。
*/
public static void testSimple() {
Fraction sum = ZERO;
for (int i=1; i<=100; i++) {
int denominator = i * (i+1);
Fraction addend = new Fraction(1, denominator);
sum = sum.add(addend);
}
System.out.println(sum);
}
/**
* 一个复杂的测试:计算 [ 1/(1*2) + 1/(2*3) + ... + 1/(2022*2023) ] - [ 1/(1*3) + 1/(3*5) + ... + 1/(2021*2023) ]
* 被减数最后的结果是 +2022/2023,减数最后的结果是 1011/2023,最终的结果应该是 1011/2023。
* 我们把所有的项存起来,完全随机打乱顺序,用来测试 Fraction 类的计算正确性和计算能力。
*/
public static void testComplex() {
java.util.ArrayList<Fraction> al = new java.util.ArrayList<Fraction>();
int quantity = 2022;
for (int i=1; i<=quantity; i++) {
int denominator = i * (i+1);
Fraction addend = new Fraction(1, denominator);
al.add(addend);
}
for (int i=1; i<=quantity-1; i+=2) {
int denominator = i * (i+2);
Fraction addend = new Fraction(1, denominator);
al.add(addend.opposite());
}
int size = al.size();
Fraction[] fractions = new Fraction[size];
al.toArray(fractions);
for (int i=0; i<size; i++) {
int pos = (int)(Math.random() * size);
Fraction temp = fractions[i];
fractions[i] = fractions[pos];
fractions[pos] = temp;
}
Fraction sum = Fraction.ZERO;
for (int i=0; i<size; i++)
sum = sum.add(fractions[i]);
System.out.println(sum);
}
public static void main(String[] args) {
testSimple();
testComplex();
}
}