برنامه نویسی

مطالعه موردی: کلاس عقلانی

این بخش نحوه طراحی را نشان می دهد گویا کلاس برای نمایش و پردازش اعداد گویا. یک عدد گویا دارای یک صورت و یک مخرج است الف/ب، جایی که آ شمارنده است و ب مخرج مثلا، 1/3، 3/4، و 10/4 اعداد گویا هستند

یک عدد گویا نمی تواند مخرج داشته باشد 0، اما یک عدد از 0 خوب است. هر عدد صحیح من معادل یک عدد گویا است i/1. اعداد گویا در محاسبات دقیق شامل کسری استفاده می شوند – برای مثال، 1/3 = 0.33333. . . . این عدد را نمی توان به طور دقیق در قالب ممیز شناور با استفاده از هر دو نوع داده نشان داد دو برابر یا شناور. برای به دست آوردن نتیجه دقیق باید از اعداد گویا استفاده کنیم.

جاوا انواع داده را برای اعداد صحیح و اعداد ممیز شناور ارائه می دهد، اما برای اعداد گویا نه. این بخش نحوه طراحی کلاسی را برای نمایش اعداد گویا نشان می دهد.

از آنجایی که اعداد گویا دارای بسیاری از ویژگی های مشترک با اعداد صحیح و اعداد ممیز شناور هستند و عدد کلاس ریشه برای کلاس های بسته بندی عددی است، مناسب است که تعریف شود گویا به عنوان یک زیر کلاس از عدد. از آنجایی که اعداد گویا قابل مقایسه هستند، گویا کلاس نیز باید پیاده سازی شود قابل مقایسه رابط. شکل زیر نشان می دهد گویا طبقه و رابطه آن با عدد کلاس و قابل مقایسه رابط.

توضیحات تصویر

یک عدد گویا از یک صورت و یک مخرج تشکیل شده است. اعداد گویا معادل زیادی وجود دارد – برای مثال، 1/3 = 2/6 = 3/9 = 4/12. صورت و مخرج 1/3 هیچ مقسوم علیه مشترکی ندارند جز 1، بنابراین 1/3 گفته می شود در پایین ترین شرایط.

برای کاهش یک عدد گویا به کمترین عبارات آن، باید بزرگترین مقسوم علیه مشترک (GCD) قدر مطلق صورت و مخرج آن را پیدا کنید، سپس صورت و مخرج را بر این مقدار تقسیم کنید. شما می توانید از روش برای محاسبه GCD دو عدد صحیح استفاده کنید n و دهمانطور که در اینجا، GreatestCommonDivisor.java پیشنهاد شده است. صورت و مخرج در a گویا شی به پایین ترین شرایط خود کاهش می یابد.
طبق معمول، اجازه دهید ابتدا یک برنامه آزمایشی بنویسیم تا دو بسازیم گویا اشیاء و روش های آن را آزمایش کنید. برنامه زیر یک برنامه آزمایشی است.

توضیحات تصویر

را اصلی روش دو عدد گویا ایجاد می کند، r1 و r2 (خطوط 7-8)، و نتایج را نمایش می دهد r1 + r2، r1 – r2، r1 x r2، و r1 / r2 (خطوط 11-14). برای اجرا r1 + r2، احضار کنید r1.add(r2) برای برگرداندن یک جدید گویا هدف – شی. به همین ترتیب، فراخوانی کنید r1.subtract(r2) برای r1 – r2، r1.multiply(r2) برای r1 x r2، و r1.divide(r2) برای r1 / r2.

را doubleValue() متد مقدار دو برابری را نشان می دهد r2 (خط 15). را doubleValue() روش در تعریف شده است java.lang.شماره و در گویا.

توجه داشته باشید که وقتی یک رشته با یک شیء با علامت مثبت (+، نمایش رشته شیء از toString() روش برای الحاق با رشته استفاده می شود. بنابراین r1 + ” + ” + r2 + ” = ” + r1.add(r2) برابر است با r1.toString() + ” + ” + r2.toString() + ” = ” + r1.add(r2).toString(). را گویا کلاس در برنامه زیر پیاده سازی شده است.

package demo;

public class Rational extends Number implements Comparable {
    // Data fields for numerator and denominator
    private long numerator = 0;
    private long denominator = 1;

    /** Construct a rational with default properties */
    public Rational() {
        this(0, 1);
    }

    /** Construct a rational with specified numerator and denominator */
    public Rational(long numerator, long denominator) {
        long gcd = gcd(numerator, denominator);
        this.numerator = ((denominator > 0) ? 1 : -1) * numerator / gcd;
        this.denominator = Math.abs(denominator) / gcd;
    }

    /** Find GCD of two numbers */
    private static long gcd(long n, long d) {
        long n1 = Math.abs(n);
        long n2 = Math.abs(d);
        int gcd = 1;

        for(int k = 1; k <= n1 && k <= n2; k++) {
            if(n1 % k == 0 && n2 % k == 0)
                gcd = k;
        }

        return gcd;
    }

    /** Return numerator */
    public long getNumerator() {
        return numerator;
    }

    /** Return denominator */
    public long getDenominator() {
        return denominator;
    }

    /** Add a rational number to this rational */
    public Rational add(Rational secondRational) {
        long n = numerator * secondRational.getDenominator() + denominator * secondRational.getNumerator();
        long d = denominator * secondRational.getDenominator();
        return new Rational(n, d);
    }

    /** Subtract a rational number to this rational */
    public Rational subtract(Rational secondRational) {
        long n = numerator * secondRational.getDenominator() - denominator * secondRational.getNumerator();
        long d = denominator * secondRational.getDenominator();
        return new Rational(n, d);
    }

    /** Multiply a rational number to this rational */
    public Rational multiply(Rational secondRational) {
        long n = numerator * secondRational.getNumerator();
        long d = denominator * secondRational.getDenominator();
        return new Rational(n, d);
    }

    /** Divide a rational number to this rational */
    public Rational divide(Rational secondRational) {
        long n = numerator * secondRational.getDenominator();
        long d = denominator * secondRational.numerator;
        return new Rational(n, d);
    }

    @Override
    public String toString() {
        if(denominator == 1)
            return numerator + "";
        else
            return numerator + "https://dev.to/" + denominator;
    }

    @Override // Override the equals method in the Object class
    public boolean equals(Object other) {
        if((this.subtract((Rational)(other))).getNumerator() == 0)
            return true;
        else
            return false;
    }

    @Override // Implement the abstract intValue method in Number
    public int intValue() {
        return (int)doubleValue();
    }

    @Override // Implement the abstract floatValue method in Number
    public float floatValue() {
        return (float)doubleValue();
    }

    @Override // Implement the abstract doubleValue method in Number
    public double doubleValue() {
        return numerator * 1.0 / denominator;
    }

    @Override // Implement the abstract longValue method in Number
    public long longValue() {
        return (long)doubleValue();
    }

    @Override // Implement the compareTo method in Comparable
    public int compareTo(Rational o) {
        if(this.subtract(o).getNumerator() > 0)
            return 1;
        else if(this.subtract(o).getNumerator() < 0)
            return -1;
        else
            return 0;
    }
}

وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

عدد گویا در یک کپسوله شده است گویا هدف – شی. در داخل، یک عدد گویا در کمترین عبارات خود نشان داده می شود (خط 15) و صورتگر علامت آن را تعیین می کند (خط 16). مخرج همیشه مثبت است (خط 17).

را gcd روش (خطوط 21-32 در گویا کلاس) خصوصی است. برای استفاده توسط مشتریان در نظر گرفته نشده است. را gcd روش فقط برای استفاده داخلی است گویا کلاس را gcd روش نیز ثابت است، زیرا به هیچ چیز خاصی وابسته نیست گویا هدف – شی.

را شکم (x) روش (خطوط 22-23 در گویا کلاس) در تعریف شده است ریاضی کلاس و مقدار مطلق را برمی گرداند ایکس.

دو گویا اشیا می توانند برای انجام عملیات جمع، تفریق، ضرب و تقسیم با یکدیگر تعامل داشته باشند. این روش ها یک روش جدید را برمی گرداند گویا شی (خطوط 45-70).

روش ها toString و برابر است در هدف – شی کلاس در گویا کلاس (خطوط 72-86). را toString() متد یک نمایش رشته ای از a را برمی گرداند گویا شی در فرم صورت / مخرج، یا به سادگی صورت کسر اگر مخرج است 1. را برابر (شیء دیگر) اگر این عدد گویا با عدد گویا دیگر برابر باشد، متد true را برمی گرداند.

روش های انتزاعی intValue، longvalue، floatValue، و دو ارزش در عدد کلاس در پیاده سازی می شوند گویا کلاس (خطوط 88-106). این روش ها را برمی گرداند بین المللی، طولانی، شناور، و دو برابر مقدار برای این عدد گویا

را مقایسه با (منطقی دیگر) روش در قابل مقایسه رابط در پیاده سازی شده است گویا کلاس (خطوط 108-116) برای مقایسه این عدد گویا با عدد گویا دیگر.

روش های گیرنده برای خواص صورت کسر و مخرج در ارائه شده اند گویا کلاس، اما متدهای تنظیم کننده ارائه نشده اند، بنابراین، یک بار a گویا شی ایجاد می شود، محتویات آن قابل تغییر نیست. را گویا کلاس تغییر ناپذیر است را رشته کلاس و کلاس های wrapper برای مقادیر نوع اولیه نیز تغییرناپذیر هستند.

صورت و مخرج با استفاده از دو متغیر نشان داده می شوند. می توان از آرایه ای از دو عدد صحیح برای نمایش صورت و مخرج استفاده کرد. امضای روش های عمومی در گویا کلاس تغییر نمی کند، اگرچه نمایش داخلی یک عدد گویا تغییر می کند. این یک مثال خوب برای نشان دادن این ایده است که فیلدهای داده یک کلاس باید خصوصی نگه داشته شوند تا پیاده سازی کلاس از استفاده از کلاس محصور شود.

را گویا کلاس محدودیت های جدی دارد و می تواند به راحتی سرریز شود. به عنوان مثال، کد زیر یک نتیجه نادرست نمایش می دهد، زیرا مخرج بسیار بزرگ است.

public class Test {
public static void main(String[] args) {
Rational r1 = new Rational(1, 123456789);
Rational r2 = new Rational(1, 123456789);
Rational r3 = new Rational(1, 123456789);
System.out.println("r1 * r2 * r3 is " +
r1.multiply(r2.multiply(r3)));
}
}

r1 * r2 * r3 is -1/2204193661661244627

برای رفع آن، می توانید آن را پیاده سازی کنید گویا کلاس با استفاده از BigInteger برای صورت و مخرج

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا