BJFU Java程序设计实验一——分数类

声明:这并不是一个完美的代码,过掉yhh没有问题,但是wjx的学生慎重选择,你可能在答辩的时候被狠狠背刺。

实验要求:

  1. 掌握类、对象、类成员变量、对象成员方法、对象的构造方法、类静态变量和类静态方法。
  2. 掌握数组的使用、掌握访问权限。
  3. 掌握Object类的重要方法,包括toString() 和 clone() 方法。
  4. 实验实现目标:实现分数类及其运算,能够实现任意的分数的单次的和批量的正确、高效的运算。

实验内容:

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();
        }
    }

  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值