Помогите понять логику

Помогите разобраться с логикой. Изначальная задача состояла в том,чтобы реализовать решение "нули функции" 3 разл.методами. Далее задача усложнилась с использованием наследования. В итоге программа состоит из нескольких классов: 1.Function (сделала его абстрактным, так как методы getFun и getDiff , как я думала, желательно переопределить в классах Solve). 2.SolveNewthonMethod 3.SplveChordMethod 4.SolveHalfDiv 5.Test Код прилагаю ниже:

package ItMethods;

abstract public class Function {

        private int power; //Наивысшая степень многочлена
        private double leftBorderA, rightBorderB, temp;
        private int counter;
        /*
        *   leftBorderA-левая граница интервала;
        *   rightBorderB- правая граница интервала;
        *   temp-временная переменная для присваивания значения;
         */


               // КОНСТРУКТОР С ПАРАМЕТРАМИ

        Function(int power, double leftBorderA, double rightBorderB) {
            this.power = power;
            this.leftBorderA = leftBorderA;
            this.rightBorderB = rightBorderB;
        }

                // КОНСТРУКТОР ИСП.В КАЧ.АРГ ОБЪЕКТ*
        Function(Function obj) {
            this.power = obj.power;
            this.leftBorderA = obj.leftBorderA;
            this.rightBorderB = obj.rightBorderB;
        }
                //  МЕТОДЫ ДОСТУПА К ПЕРЕМЕННЫМ РОДИТ.КЛАССА


    public void setPower(int power) {
        this.power = power;
    }

    public void setLeftBorderA(double leftBorderA) {
        this.leftBorderA = leftBorderA;
    }

    public void setRightBorderB(double rightBorderB) {
        this.rightBorderB = rightBorderB;
    }

    public int getPower() {
        return power;
    }

    public double getLeftBorderA() {
        return leftBorderA;
    }

    public double getRightBorderB() {
        return rightBorderB;
    }

                // ЗАМЕЧАНИЕ И ПРОВЕРКА

        void checkIntervalBoundary(){
            if (power % 2 == 1) System.out.println("Так как старшая степень " +
                    "полинома равна " + power + " ,то следует,что полином \n" +
                    " имеет хотя-бы один действительный корень. ");

            if (leftBorderA > rightBorderB) {
                temp = rightBorderB;
                rightBorderB = leftBorderA;
                leftBorderA = temp;
            }
            System.out.println("Интервал: ["+leftBorderA+";"+rightBorderB+"]");

        }


        abstract double getFun(double inApprox);

        abstract double getDiffFun1(double inApprox);

        abstract double getDiffFun2(double inApprox);

    }



package ItMethods;


public class SolveNewthonMethod extends Function{
    private double inApprox;
    private double epsilon,error;
    private boolean b1,b2,b3,b4;
    private double res,tmp1,tmp2,tmp3;

                // КОНСТРУКТОР
    SolveNewthonMethod(int power,double leftBorA,double rightBorB,double epsilon) {
        super(power, leftBorA, rightBorB);
        this.epsilon = epsilon;
        tmp1=getLeftBorderA();
        tmp2=getRightBorderB();
        tmp3=getPower();
    }

    void choseApprox(){
        for (double i = tmp1; i <= tmp2; i +=epsilon) {
            if (getDiffFun1(i) > 0 &&
                    getDiffFun2(i) > 0 ||
                    getDiffFun1(i) < 0 &&
                            getDiffFun2(i) < 0){
                inApprox = tmp2;
            } else inApprox = tmp1;
        }
    }

            //МЕТОДЫ ДОСТУПА К ПРЕМЕННОЙ ЭКЗ.КЛАССА


    public void setEpsilon(double epsilon) {
        this.epsilon = epsilon;
    }

    public double getEpsilon() {
        return epsilon;
    }

                //ПЕРЕОПРЕДЕЛЕНИЕ ФУНКЦИЙ

    double getFun(double inApprox) {
        return Math.pow(inApprox,tmp3)-3*Math.pow(inApprox,tmp3-2)
                -4*Math.pow(inApprox,tmp3-3)+2*inApprox+4;
    }

    double getDiffFun1(double inApprox) {
        return tmp3*Math.pow(inApprox,tmp3-1)
                -3*(tmp3-2)*Math.pow(inApprox,tmp3-3)
                -4*(tmp3-3)*Math.pow(inApprox,tmp3-4)+2;
    }

    double getDiffFun2(double inApprox){
        return tmp3*(tmp3-1)*Math.pow(inApprox,tmp3-2)
                -3*(tmp3-2)*(tmp3-3)*Math.pow(inApprox,tmp3-4)
                -4*(tmp3-3)*(tmp3-4)*Math.pow(inApprox,tmp3-5);
    }
                // ДОСТАТОЧНЫЕ УСЛОВИЯ

    // 1е достаточное условие: f(a)*f(b)<0
    boolean checkFun(){
        if(getFun(tmp1)*getFun(tmp2)<0){
            System.out.println("Уравнение точно имеет хотя бы один корень.");
            b1=true;
        }
        return b1;
    }

    // 2e достаточное условие: x0 должно удовлетворять f(x0)*f``(x0)>0
    boolean checkInApprox() {
        if (getFun(inApprox) * getDiffFun2(inApprox) > 0) {
            System.out.println("Верное приближение");
            return b2 = true;
        } else {
            System.out.println("Начальное приближнение не удовлетворяет условию f`(x0)*f``(x0)>0.");
            return false;
        }
    }

    //3е достаточное условие: 1я Производная не должна = 0 и должна сохр знак для всех х
    // из промежутка от а до b. В качестве шага взята точность.
    boolean checkDiff(){

        for(double i=tmp1;i<=tmp2;i+=epsilon){
            if(getDiffFun1(i)!=0 && (getDiffFun1(i)>0 || getDiffFun1(i)<0)){
                b3=true;
            }
        }
        return b3;
    }

    //4е достаточное условие: 2я Производная должна сохранять знак на всем интервале
    boolean checkDiff1() {
        for (double i = tmp1; i <= tmp2; i += epsilon) {
            if (getDiffFun2(i) > 0 || getDiffFun2(i) < 0) {
                b4 = true;
            }
        }
        return b4;
    }

    void solve(){
        if(b1 && b2 && b3 && b4  ) {
            do {
                res = inApprox - getFun(inApprox) / getDiffFun1(inApprox);
                error=res-inApprox;
                inApprox=res;
                System.out.println(+res);
            } while (Math.abs(error) > epsilon );

        }
        else System.out.println("Не выполнено одно из достаточных условий!");
    }
}

package ItMethods;

public class SolveChordMethod extends Function{
    private double inApprox;
    private double epsilon,res,error;
    private double tmp1,tmp2,tmp3;

                //КОНСТРУКТОР С ПАРАМЕТРАМИ
    SolveChordMethod(int power,double leftBorA,double rightBorB,double epsilon) {
        super(power, leftBorA, rightBorB);
        this.epsilon = epsilon;
        tmp1 = getLeftBorderA();
        tmp2 = getRightBorderB();
        tmp3 = getPower();
    }

            // ОПРЕДЕЛЕНИЕ НАЧАЛЬНОГО ПРИБЛИЖЕНИЯ inApprox
    void checkInApprox(){
        for (double i = tmp1; i < tmp2; i += epsilon) {
            if (getDiffFun2(i) * getFun(tmp1) > 0) {
                inApprox = tmp2;
            }
            if (getDiffFun2(i) * getFun(tmp2) > 0) {
                inApprox = tmp1;
            }
        }
    }
            //ПЕРЕОПРЕДЕЛЕНИЕ МЕТОДОВ
    //@Override
    double getFun(double inApprox) {
        return Math.pow(inApprox,tmp3)-3*Math.pow(inApprox,tmp3-2)
                -4*Math.pow(inApprox,tmp3-3)+2*inApprox+4;
    }

    double getDiffFun1(double inApprox) {
        return tmp3*Math.pow(inApprox,tmp3-1)
                -3*(tmp3-2)*Math.pow(inApprox,tmp3-3)
                -4*(tmp3-3)*Math.pow(inApprox,tmp3-4)+2;
    }

    double getDiffFun2(double inApprox){
        return tmp3*(tmp3-1)*Math.pow(inApprox,tmp3-2)
                -3*(tmp3-2)*(tmp3-3)*Math.pow(inApprox,tmp3-4)
                -4*(tmp3-3)*(tmp3-4)*Math.pow(inApprox,tmp3-5);
    }

                //МЕТОД РЕШЕНИЯ
    void solve(){
        if(inApprox==tmp2){
            do{
                res=inApprox -getFun(inApprox)/(getFun(inApprox)-getFun(tmp1))*(inApprox-tmp1);
                error=res-inApprox;
                System.out.println(+res);
                inApprox=res;
            }while (Math.abs(error)>=epsilon);

        }
        if(inApprox==tmp1){
            do{
                res=inApprox-getFun(inApprox)/(getFun(tmp2)-getFun(inApprox))*(tmp2-inApprox);
                error=res-inApprox;
                System.out.println(+res);
                inApprox=res;
            }while (Math.abs(error)>=epsilon);
        }
        else System.out.println("Ошибка");
    }
}

package ItMethods;

public class SolveHalfDiv extends Function{

   private double pointDiv,error;
   private double epsilon;
   private double tmp1,tmp2,tmp3;

            //КОНСТРУКТОР С ПАРАМЕТРАМИ
    SolveHalfDiv(int power,double leftBorA,double rightBorB ,double epsilon){
        super(power,leftBorA,rightBorB);
        this.epsilon=epsilon;
        tmp1=getLeftBorderA();
        tmp2=getRightBorderB();
        tmp3=getPower();
    }

            //КОНСТРУКТОР С ОБЪЕКТОМ*
    SolveHalfDiv(Function obj1,double epsilon) {
        super(obj1);
        this.epsilon=epsilon;
    }

            //МЕТОДЫ ДОСТУПА К ПЕРЕМЕННЫМ ЭКЗЕМПЛЯРА


    public void setEpsilon(double epsilon) {
        this.epsilon = epsilon;
    }

    public double getEpsilon() {
        return epsilon;
    }
            //ПЕРЕОПРЕДЕЛЕНИЕ АБСТРАКТНЫХ МЕТОДОВ

    double getFun(double inApprox) {
        return Math.pow(inApprox,tmp3)-3*Math.pow(inApprox,tmp3-2)
                -4*Math.pow(inApprox,tmp3-3)+2*inApprox+4;
    }

    double getDiffFun1(double inApprox) {
        return tmp3*Math.pow(inApprox,tmp3-1)
                -3*(tmp3-2)*Math.pow(inApprox,tmp3-3)
                -4*(tmp3-3)*Math.pow(inApprox,tmp3-4)+2;
    }

    double getDiffFun2(double inApprox){
        return tmp3*(tmp3-1)*Math.pow(inApprox,tmp3-2)
                -3*(tmp3-2)*(tmp3-3)*Math.pow(inApprox,tmp3-4)
                -4*(tmp3-3)*(tmp3-4)*Math.pow(inApprox,tmp3-5);
    }
    //Function s= new Function(5,1.8,2.3);
    //Function obg=new SolveHalfDiv(0.02);
    void solve(){

        if(getFun(tmp1)*getFun(tmp2)<0){
            pointDiv=(tmp1+tmp2)/2;
            do{
                if(getFun(tmp1)*getFun(pointDiv)<0){
                    tmp2=pointDiv;
                    error=tmp1-pointDiv;
                }
                if(getFun(tmp2)*getFun(pointDiv)<0){
                    tmp1=pointDiv;
                    error=tmp2-pointDiv;
                }
                pointDiv=(tmp1+tmp2)/2;

                System.out.println();
                System.out.println(+pointDiv);
            }while (Math.abs(error)>epsilon);
        }
        else System.out.println("Не выполняются требования для использования данного метода.");

    }
}

package ItMethods;

public class Test {
    public static void main(String[] args) {

                    // Проверка SolveHalfDiv
        /*
        SolveHalfDiv obj = new SolveHalfDiv(5, 1.8, 2.3, 0.01);
        //SolveHalfDiv obj1=new SolveHalfDiv(obj,0.01);
        obj.checkIntervalBoundary();
        obj.solve();
         */

                    // Проверка SolveChordMethod
        /*
        SolveChordMethod obj1=new SolveChordMethod(5,1.8,2.3,0.01);
        obj1.checkIntervalBoundary();
        obj1.checkInApprox();
        obj1.solve();
         */

                    // Проверка SolveNewtonMethod
        SolveNewthonMethod obj2=new SolveNewthonMethod(5,1.8,2.3,0.01);
        obj2.checkIntervalBoundary();
        obj2.choseApprox();
        obj2.checkInApprox();
        obj2.checkFun();
        obj2.checkDiff();
        obj2.checkDiff1();
        obj2.solve();


    }
}

Однако,сейчас задача свелась к реализации нового класса Polynomial ,который должен унаследовать класс Function и иметь модификатор final,в котором будут методы getFun и getDiff,однако,я не очень понимаю логику данной реализации.Зачем создавать данный класс? И как, в дальнейшем, использовать этот класс?


Ответы (1 шт):

Автор решения: Ramiz

может я конечно и ошибаюсь, но мне кажется, что Вы не правильно смоделировали (или поняли) задачу.

ООП используют чтобы облегчить понимание, а не запутать того кто читает код.

Поэтому мы моделируем так как это выглядит в предметной области, например: у нес есть задача нахождения нулей различных функций различными методами. Это утверждение уже подсказывает нам две сущности - Function (F) и Method (M). Причем F - это любая функция, а M - метод нахождения нулей для любой функции.

упрощенный пример кода:

interface Function {
  double get(double x);
}

abstract class BoundedFunction implements Function {
  double leftBorder;
  double rightBorder;
}

abstract class Method {
  public abstract Solution solve(Function f);
}
class Solution {
  double[] zeros;
}

final class PolynomialFunction extends Function {
  final int power;
  double[] c;
  PolynomialFunction(double... c) {
    this.c = c; // TODO check that highest c is not zero, clone, inverse array if needed, etc
    this.power = c.length;
  }
  double get(double x) {
    // TODO check borders, etc
    double y = 0;
    for(int i = 0; i < power; i++) {
      y += Math.pow(x, i) * c[i];
    }
    return y;
  }
}

class DichotomyMethod extends Method {
  // ...
  Solution solve(Function f) {
    // TODO implement "half div" method
    return solution;
  }
}

// tests
Method m = new DichotomyMethod();
m.solve(new PolynomialFunction(0, 1)); // y = x
m.solve(new PolynomialFunction(0, 0, 1)); // y = x^2
m.solve(x -> Math.sin(x)); // y = sin(x) как лямбда, если нужно

Method[] methods = {new DichotomyMethod(), new NewtonMethod() /* , ... */};
Function[] functions = {
  new PolynomialFunction(0, -1),
  new PolynomialFunction(0, 2, -1),
  x -> Math.cos(x),
  x -> Math.pow(2, x) /*, etc */};

for(Function f : functions) {
  System.out.println("Compare different methods for function: " + f);
  for(Method m : methods) {
    System.out.println(m.solve(f));
  }
}

итд

→ Ссылка