而不是教你什么样规范地、科学地用java求出函数在好几的导数,而不是教你如何规范地、科学地用java求出函数在有个别的导数

首先声贝拉米点,本文重要介绍的是面向对象(OO)的斟酌,顺便谈下函数式编制程序,而不是教你怎么准确地、科学地用java求出函数在有些的导数。

先是声多美滋(Dumex)点,本文主要介绍的是面向对象(OO)的思维,顺便谈下函数式编制程序,而不是教您怎么着准确地、科学地用java求出函数在有个别的导数。

 

 

一、引子

 

def d(f) :
    def calc(x) :
        dx = 0.000001  # 表示无穷小的Δx
        return (f(x+dx) - f(x)) / dx  # 计算斜率。注意,此处引用了外层作用域的变量 f
    return calc  # 此处用函数作为返回值(也就是函数 f 的导数)
# 计算二次函数 f(x) = x2 + x + 1的导数
f = lambda x : x**2 + x + 1  # 先把二次函数用代码表达出来
f1 = d(f)# 这个f1 就是 f 的一阶导数啦。注意,导数依然是个函数
# 计算x=3的斜率
f1(3)
# 二阶导数
f2 = d(f1)

先是,直接上一段python代码,请大家先分析下方面代码是用如何措施求导的。请不要被那段代码吓到,你无需纠结它的语法,只要知道它的求导思路。

如上代码引用自《何以小编推荐 Python[4]:作为函数式编制程序语言的
Python
》,那篇博客是敦促自身写篇小说的主要原因。

博主说“要是不用 FP,改用 OOP,上述须求该怎么贯彻?作者觉得吧,用 OOP
来求导,那代码写起来多半是又丑又臭。”

自家满腹狐疑,于是就用面向对象的java试了试,最终也没多少代码。假若用java八或之后版本,代码越来越少。

请大家想想1个难点,怎么着用面向对象的笔触改写这几个程序。请先好好思虑,尝试编个程序再持续往下看。

设想到看到那一个标题进来的同室大多是学过java的,下边笔者用java,用面向对象的思路一步步分析这么些标题。

 

一、引子

 

def d(f) :
    def calc(x) :
        dx = 0.000001  # 表示无穷小的Δx
        return (f(x+dx) - f(x)) / dx  # 计算斜率。注意,此处引用了外层作用域的变量 f
    return calc  # 此处用函数作为返回值(也就是函数 f 的导数)
# 计算二次函数 f(x) = x2 + x + 1的导数
f = lambda x : x**2 + x + 1  # 先把二次函数用代码表达出来
f1 = d(f)# 这个f1 就是 f 的一阶导数啦。注意,导数依然是个函数
# 计算x=3的斜率
f1(3)
# 二阶导数
f2 = d(f1)

第一,直接上一段python代码,请大家先分析下方面代码是用怎么着方法求导的。请不要被那段代码吓到,你无需纠结它的语法,只要了解它的求导思路。

如上代码引用自《为啥我推荐 Python[4]:作为函数式编制程序语言的
Python
》,那篇博客是敦促自身写篇小说的第叁缘由。

博主说“即便不用 FP,改用 OOP,上述须要该怎么贯彻?小编觉得吧,用 OOP
来求导,那代码写起来多半是又丑又臭。”

本人半信不信,于是就用面向对象的java试了试,最终也没多少代码。假设用java捌或今后版本,代码更加少。

请大家想想1个难点,如何用面向对象的思路改写那些顺序。请先好好思念,尝试编个程序再持续往下看。

怀恋到看到那些标题进来的校友大多是学过java的,上边小编用java,用面向对象的思绪一步步剖析那么些标题。

 

二、求导

 

小说开始笔者已近证明过了,本文不是来钻探数学的,求导只是笔者用来表明面向对象的多少个例子。

尽管您早就忘了开头那段代码的求导思路,请回头再看看,看看用python是什么样求导的。

深信您只要听新闻说过求导,肯定壹眼就观察起初那段代码是用导数概念求导的。

公海赌船网址 1

代码中只是将无穷小Δx粗略地算做贰个较小的值0.000001。

 

二、求导

 

作品开头作者已近表明过了,本文不是来研究数学的,求导只是自家用来证实面向对象的1个例子。

设若您曾经忘了始于那段代码的求导思路,请回头再看看,看看用python是什么样求导的。

相信您假若听他们讲过求导,肯定一眼就观看初步那段代码是用导数概念求导的。

公海赌船网址 2

代码中只是将无穷小Δx粗略地算做2个较小的值0.00000一。

 

三、最初的想法

 

//自定义函数
public class Function {
    //函数:f(x) = 3x^3 + 2x^2 + x + 1
    public double f(double x) {
        return 3 * x * x * x + 2 * x * x + x + 1;
    }
}

//一元函数导函数
public class DerivedFunction {
    //表示无穷小的Δx
    private static final double DELTA_X = 0.000001;
    //待求导的函数
    private Function function;

    public DerivedFunction(Function function) {
        this.function = function;
    }

    /**
     * 获取function在点x处的导数
     * @param x 待求导的点
     * @return 导数
     */
    public double get(double x) {
        return (function.f(x + DELTA_X) - function.f(x)) / DELTA_X;
    }
}

public class Main {
    public static void main(String[] args) {
        //一阶导函数
        DerivedFunction derivative = new DerivedFunction(new Function());
        //打印函数在x=2处的一阶导数
        System.out.println(derivative.get(2));
    }
}

先声澳优(Ausnutria Hyproca)点,想念到博客篇幅,笔者利用了不规范的代码注释,希望大家不要被作者误导。

自笔者想若是大家能够思量了,应该至少会想到这步吧。代码笔者就不解释了,作者只是用java改写了稿子初阶的这段python代码,做了二个简约的翻译工作。再请咱们着想下以上代码的题材。

刚开端,小编探究这些难点想开的是建2个名称为Function的类,类中有2个名称叫f的措施。但牵记到要每一趟须求新的函数导数时就得改变那一个f方法的落实,分明不便利扩大,那违背了开闭原则

估摸有的同学没听过那一个词,小编就分解下:”目的(类,模块,函数等)应对扩张开放,但对修改封闭“。

于是乎小编就没继续写下去,但为了让大家直观的感触到这几个想法,笔者写那篇博客时就贯彻了瞬间这一个想法。

请大家想想一下如何重构代码以消除扩大性难点。

 

三、最初的想法

 

//自定义函数
public class Function {
    //函数:f(x) = 3x^3 + 2x^2 + x + 1
    public double f(double x) {
        return 3 * x * x * x + 2 * x * x + x + 1;
    }
}

//一元函数导函数
public class DerivedFunction {
    //表示无穷小的Δx
    private static final double DELTA_X = 0.000001;
    //待求导的函数
    private Function function;

    public DerivedFunction(Function function) {
        this.function = function;
    }

    /**
     * 获取function在点x处的导数
     * @param x 待求导的点
     * @return 导数
     */
    public double get(double x) {
        return (function.f(x + DELTA_X) - function.f(x)) / DELTA_X;
    }
}

public class Main {
    public static void main(String[] args) {
        //一阶导函数
        DerivedFunction derivative = new DerivedFunction(new Function());
        //打印函数在x=2处的一阶导数
        System.out.println(derivative.get(2));
    }
}

先声惠氏(Beingmate)点,思量到博客篇幅,笔者使用了不正规的代码注释,希望大家不用被自个儿误导。

本人想只要我们美好考虑了,应该至少会想到那步吧。代码作者就不表明了,小编只是用java改写了文章起头的那段python代码,做了二个简单易行的翻译工作。再请大家着想下以上代码的难点。

刚开头,作者合计那一个标题想开的是建1个名字为Function的类,类中有3个名字为f的方法。但思索到要每一趟供给新的函数导数时就得改变那一个f方法的落到实处,鲜明不便于增添,那违反了开闭原则

估价有的同学没听过这么些词,小编就表明下:”指标(类,模块,函数等)应对扩展开放,但对修改封闭“。

于是乎我就没继续写下去,但为了让我们直观的感触到那一个想法,我写那篇博客时就贯彻了须臾间那几个想法。

请我们想想一下什么样重构代码以缓解扩大性难点。

 

肆、初始的想法

 

估价学过面向对象的同学会想到把Function类改成接口或抽象类,未来每一回添加新的函数时借使重写那几个接口或抽象类中的f方法,那正是面向接口编制程序,符合借助于反转原则,下边包车型客车代码便是那般做的。

再声称一点,思考到篇幅的难点,前面包车型地铁代码作者会省去与前面代码重复的注释,有不知底的地点还请看看上三个想法中的代码。

//一元函数
public interface Function {
    double f(double x);
}

//自定义的函数
public class MyFunction implements Function {
    @Override
    public double f(double x) {
        return 3 * x * x * x + 2 * x * x + x + 1;
    }
}

public class DerivedFunction {
    private static final double DELTA_X = 0.000001;
    private Function function;

    public DerivedFunction(Function function) {
        this.function = function;
    }

    public double get(double x) {
        return (function.f(x + DELTA_X) - function.f(x)) / DELTA_X;
    }
}

public class Main {
    public static void main(String[] args) {
        //一阶导函数:f'(x) = 9x^2 + 4x + 1
        DerivedFunction derivative = new DerivedFunction(new MyFunction());
        System.out.println(derivative.get(2));
    }
}

自己想认真看的同班可能会发觉三个题材,笔者的翻译做的还不到位,开首那段python代码还足以轻松地求出二阶导函数(导数的导数),而本人的代码却13分。

其实假使稍加修改上述代码的一个地点就足以轻松达成求二阶导,请再想想片刻。

 

肆、初叶的想法

 

估价学过面向对象的同学会想到把Function类改成接口或抽象类,今后每一遍添加新的函数时假使重写那一个接口或抽象类中的f方法,那正是面向接口编制程序,符合正视反转原则,上面包车型地铁代码便是那样做的。

再声圣元点,思索到篇幅的难题,前边的代码作者会省去与事先代码重复的诠释,有不知道的地点还请看看上二个想法中的代码。

//一元函数
public interface Function {
    double f(double x);
}

//自定义的函数
public class MyFunction implements Function {
    @Override
    public double f(double x) {
        return 3 * x * x * x + 2 * x * x + x + 1;
    }
}

public class DerivedFunction {
    private static final double DELTA_X = 0.000001;
    private Function function;

    public DerivedFunction(Function function) {
        this.function = function;
    }

    public double get(double x) {
        return (function.f(x + DELTA_X) - function.f(x)) / DELTA_X;
    }
}

public class Main {
    public static void main(String[] args) {
        //一阶导函数:f'(x) = 9x^2 + 4x + 1
        DerivedFunction derivative = new DerivedFunction(new MyFunction());
        System.out.println(derivative.get(2));
    }
}

本身想认真看的同学可能会发觉一个题材,笔者的翻译做的还不成功,开始那段python代码还是能轻松地求出二阶导函数(导数的导数),而自个儿的代码却百般。

实则只要稍加修改上述代码的贰个地点就能够轻松完毕求二阶导,请再想想片刻。

 

伍、后来的想法

 

当本人写出地点的代码时,笔者感觉完全能够矢口否认“用 OOP
来求导,那代码写起来多半是又丑又臭”的见识。但还不能够求二阶导,笔者有点不甘心。

于是自个儿就动笔,列了一晃用定义求1阶导和求二阶导的姿态,想了想七个姿态的分别与交流,突然想到导函数也是函数。

DerivedFunction的get方法和Function的f方法的参数和重返值1样,DerivedFunction能够兑现Function接口,于是暴发了上边包车型大巴代码。

public interface Function {
    double f(double x);
}

public class DerivedFunction implements Function {
    private static final double DELTA_X = 0.000001;
    private Function function;

    public DerivedFunction(Function function) {
        this.function = function;
    }

    @Override
    public double f(double x) {
        return (function.f(x + DELTA_X) - function.f(x)) / DELTA_X;
    }
}

public class Main {
    public static void main(String[] args) {
        Function f1 = new DerivedFunction(new Function() {
            @Override
            public double f(double x) {
                return 3 * x * x * x + 2 * x * x + x + 1;
            }
        });
        System.out.println(f1.f(2));
        //二阶导函数:f''(x) = 18x + 4
        Function f2 = new DerivedFunction(f1);
        //打印函数f(x) = 3x^3 + 2x^2 + x + 1在x=2处的二阶导数
        System.out.println(f2.f(2));
    }
}

设想到1些同学没学过java八或上述版本,以上代码未有运用java捌函数式编制程序的新特征。 

比方您接触过java捌,请思虑如何改写以上代码,使其更不难。

 

伍、后来的想法

 

当本身写出地点的代码时,小编深感完全能够矢口否认“用 OOP
来求导,那代码写起来多半是又丑又臭”的意见。但还无法求二阶导,笔者有点不甘心。

公海赌船网址,于是乎小编就动笔,列了须臾间用定义求一阶导和求二阶导的架势,想了想七个姿态的界别与联络,突然想到导函数也是函数。

DerivedFunction的get方法和Function的f方法的参数和重返值一样,DerivedFunction可以达成Function接口,于是爆发了上面包车型客车代码。

public interface Function {
    double f(double x);
}

public class DerivedFunction implements Function {
    private static final double DELTA_X = 0.000001;
    private Function function;

    public DerivedFunction(Function function) {
        this.function = function;
    }

    @Override
    public double f(double x) {
        return (function.f(x + DELTA_X) - function.f(x)) / DELTA_X;
    }
}

public class Main {
    public static void main(String[] args) {
        Function f1 = new DerivedFunction(new Function() {
            @Override
            public double f(double x) {
                return 3 * x * x * x + 2 * x * x + x + 1;
            }
        });
        System.out.println(f1.f(2));
        //二阶导函数:f''(x) = 18x + 4
        Function f2 = new DerivedFunction(f1);
        //打印函数f(x) = 3x^3 + 2x^2 + x + 1在x=2处的二阶导数
        System.out.println(f2.f(2));
    }
}

设想到部分同学没学过java8或上述版本,以上代码未有应用java捌函数式编制程序的新性情。 

倘若您接触过java8,请思量怎么改写以上代码,使其更简明。

 

六、最终的想法

 

public class DerivedFunction implements Function<Double, Double> {
    private static final double DELTA_X = 0.000001;
    private Function<Double, Double> function;

    public DerivedFunction(Function<Double, Double> function) {
        this.function = function;
    }

    @Override
    public Double apply(Double x) {
        return (function.apply(x + DELTA_X) - function.apply(x)) / DELTA_X;
    }
}

public class Main {
    public static void main(String[] args) {
        //打印函数在x=2处的二阶导
        System.out.println(new DerivedFunction(new DerivedFunction(x -> 3 * x * x * x + 2 * x * x + x + 1)).apply(2.0));
    }
}

前边几个想法为了扩充Function接口,使用了表面类、匿名类的不2秘籍,其实也足以用当中类。而那在那里,笔者用了lambda表达式,是不是更简洁了。

此间用的Function接口用的是jdk自带的,我们不需求团结定义了。因为那是3个函数式接口,大家能够用lambda方便地落到实处。后来意识,其实那里用UnaryOperator其一接口更适合。

当今大家有未有发现,用java、用OOP也能够13分简短地落实求导,并不如初始的这段python代码麻烦很多。

 

6、最后的想法

 

public class DerivedFunction implements Function<Double, Double> {
    private static final double DELTA_X = 0.000001;
    private Function<Double, Double> function;

    public DerivedFunction(Function<Double, Double> function) {
        this.function = function;
    }

    @Override
    public Double apply(Double x) {
        return (function.apply(x + DELTA_X) - function.apply(x)) / DELTA_X;
    }
}

public class Main {
    public static void main(String[] args) {
        //打印函数在x=2处的二阶导
        System.out.println(new DerivedFunction(new DerivedFunction(x -> 3 * x * x * x + 2 * x * x + x + 1)).apply(2.0));
    }
}

事先几个想法为了扩张Function接口,使用了外部类、匿名类的法子,其实也可以用当中类。而那在这里,笔者用了lambda表达式,是还是不是更简洁了。

此间用的Function接口用的是jdk自带的,大家不须要自个儿定义了。因为这是一个函数式接口,大家得以用lambda方便地促成。后来意识,其实那里用UnaryOperator以此接口更合适。

今后大家有没有觉察,用java、用OOP也得以11分简洁地落到实处求导,并比不上开始的那段python代码麻烦很多。

 

7、编制程序范式

 

在俺眼里,编制程序范式简单的说的话就是编制程序的一种格局,1种风格。

自家先介绍个中的八个,你基本上就驾驭它的意思了。

 

7、编制程序范式

 

以作者之见,编制程序范式简单来讲来说就是编制程序的1种形式,一种风格。

自个儿先介绍个中的四个,你差不离就清楚它的意义了。

 

7.1 面向对象程序设计(OOP)

观看此间的同校应该对面向对象有了更加直观的认识。在面向对象编制程序中,万物皆对象,抽象出类的概念。基本特点是包装、继承、多态,认识不深的同窗能够再去作者前边的代码中找找这么些特色。

本人事先还介绍了面向对象的多少个规格:开闭原则注重反转原则。其余还有单一职务规范里氏替换原则接口隔绝原则。这是面向对象的陆个着力尺度,合称SOLID)。

 

7.1 面向对象程序设计(OOP)

见状这里的同班应该对面向对象有了越来越直观的认识。在面向对象编制程序中,万物皆对象,抽象出类的定义。基本性情是包裹、继承、多态,认识不深的同校能够再去笔者前边的代码中找找那三个特色。

自个儿前面还介绍了面向对象的几个原则:开闭原则看重反转原则。其余还有单1职分规范里氏替换原则接口隔断原则。那是面向对象的四个为主尺度,合称SOLID)。

 

7.2 函数编制程序语言(FP)

正文早先那段代码用的就是python函数式编制程序的语法,后来自身又用java捌函数式编制程序的语法翻译了那段代码。

信任你已经直观地感受到它的简练,以函数为核心,几行代码就消除了求导的题目。

 

7.2 函数编制程序语言(FP)

本文开首那段代码用的正是python函数式编程的语法,后来本身又用java八函数式编制程序的语法翻译了那段代码。

深信你已经直观地感受到它的简洁,以函数为主导,几行代码就一挥而就了求导的标题。

 

7.3 进程式编制程序(Procedural programming)

约莫学过编制程序都学过C,C语言就是1种进度式编制程序语言。在作者眼里,进程式编制程序大致正是为着实现七个供给,像记流水帐一样,平铺直叙下去。 

       

7.3 进程式编制程序(Procedural programming)

大体学过编制程序都学过C,C语言就是一种进度式编制程序语言。在笔者眼里,进度式编制程序大致正是为了实现三个要求,像记流水帐1样,平铺直叙下去。 

       

八、结尾

 

由于自身初学java,方今只能想到这么多。如若大家有更加好的想法依旧觉的自家上面说的至极,欢迎评论,望各位不吝赐教。

那是作者的第一篇技术博客,但愿自身说知道了面向对象。假若对您有帮带,请点个赞只怕评论下,给小编点持续创作的重力。

八、结尾

 

出于自己初学java,如今只可以想到那样多。要是大家有越来越好的想法依然觉的自家上边说的有标题,欢迎评论,望各位不吝赐教。

那是本人的率先篇技术博客,但愿笔者说通晓了面向对象。若是对你有赞助,请点个赞也许评论下,给本身点持续创作的动力。

相关文章