Помогите понять логику
Помогите разобраться с логикой. Изначальная задача состояла в том,чтобы реализовать решение "нули функции" 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 шт):
может я конечно и ошибаюсь, но мне кажется, что Вы не правильно смоделировали (или поняли) задачу.
ООП используют чтобы облегчить понимание, а не запутать того кто читает код.
Поэтому мы моделируем так как это выглядит в предметной области, например: у нес есть задача нахождения нулей различных функций различными методами. Это утверждение уже подсказывает нам две сущности - 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));
}
}
итд