新普金娱乐网址


从中国象棋和国际象棋来说东西方文化的距离

以农学的意见看生活(连载二)数学

数学【译】数据体现:中国的程序员是社会风气上最牛的程序员

  • 一月 01, 2019
  • 数学
  • 没有评论

首先讲明一点,本文紧要介绍的是面向对象(OO)的思考,顺便谈下函数式编程,而不是教你怎么样规范地、科学地用java求出函数在少数的导数。

写在面前:直接认为中国的程序员想法多,肯钻研肯学习,但却不知底原来中国的程序员是社会风气上最牛的程序员。说来可能不信,但依据HackerRank官网的一篇通讯,数据体现中华的程序员就是世界上最牛的程序员。特将此文翻译成粤语,分享给大家。

 

假若问哪个地方的程序员最牛,很五人自然会以为是美国。毕竟美国有着众多典型的程序员,如比尔(比尔(Bill))·盖茨、
肯·Thompson、 C
语言之父丹喀布尔(Denis)·里奇(Richie)、唐纳德(Donald)·克努特。然则,这个年,印度的程序员规模增长是大地最快的,俄罗丝的黑客也进一步锋芒毕露。有什么点子来确定哪些国家的程序员是最牛的吗?

一、引子

 

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试了试,最终也没多少代码。假设用java8或之后版本,代码更少。

请我们想想一个问题,如何用面向对象的思路改写这多少个顺序。请先好好考虑,尝试编个程序再持续往下看。

考虑到看到这个题目进来的同学大多是学过java的,下面我用java,用面向对象的思路一步步分析那些题目。

 

在HackerRank网站上,哪些国家在编程挑衅赛中展现最厉害呢?通过数量,大家期望可以找到题目的答案。

二、求导

 

作品起头我已近阐明过了,本文不是来研商数学的,求导只是自家用来证实面向对象的一个例证。

如果你已经忘了起头这段代码的求导思路,请回头再看看,看看用python是咋样求导的。

信任你假使听说过求导,肯定一眼就看出伊始这段代码是用导数概念求导的。

数学 1

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

 


HackerRank网站上,为了协理程序员进步技术,我们举办过数以千计的编程挑衅赛。来自世界各地成千上万的程序员加入了这多少个挑战赛,从
Python
到算法到安全到分布式系统都有提到。我们的社区也有跨越150万开发者的名次,并且社区的人数每日都在增长。

三、最初的想法

 

//自定义函数
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));
    }
}

先表明一点,考虑到博客篇幅,我利用了不正经的代码注释,希望我们不要被自己误导。

自家想只要我们可以考虑了,应该至少会想到这步吧。代码我就不表达了,我只是用java改写了作品初步的这段python代码,做了一个粗略的翻译工作。再请我们着想下以上代码的题材。

刚起始,我研究这一个问题想开的是建一个名为Function的类,类中有一个名为f的不二法门。但考虑到要每一回要求新的函数导数时就得改变这些f方法的实现,分明不便利增加,这违背了开闭原则

揣摸有的同学没听过这多少个词,我就表明下:”目的(类,模块,函数等)应对扩展开放,但对修改封闭“。

于是乎我就没继续写下去,但为了让我们直观的感想到这么些想法,我写这篇博客时就贯彻了刹那间这些想法。

请我们想想一下怎么样重构代码以缓解增加性问题。

 

遵照我们的数额展现,中国和俄联邦(Rose)有着最具才情的程序员。中国程序员在数学、功用程序设计和数据结构方面超越了世道其他国家的程序员,而俄罗丝程序员则在算法领域占有主导地位,算法也是最风靡和最具竞争力的圈子。尽管花旗国和孔雀之国在HackerRank上也有众多名特优的程序员,但他们也只可以排在第28和第31。

四、开端的想法

 

推测学过面向对象的同学会想到把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代码还是可以够轻松地求出二阶导函数(导数的导数),而自己的代码却百般。

其实只要稍加修改上述代码的一个地点就可以轻松实现求二阶导,请再想想片刻。

 

1、全体综合排行

俺们先从程序员中最受欢迎的测试项目最先分析。HackerRank程序员可挑选出席15个不等世界,下表展现了各样领域的百分比

数学 2
远远超过的小圈子是算法领域,这一个领域取得了近40%的程序员青睐。这几个圈子包括数据排序,动态编程,搜索关键字和其他依据逻辑的职责方面的挑衅。对于算法测试,程序员可利用他们选拔的言语,这说不定也诠释了该领域如此受欢迎的一对原因。排在第二位和第三位的Java和数量架构分别都占到了接近
10%的百分比。而分布系统和安全的占比最低。

那么,基于这么些测试,哪个国家的程序员全体得分最高呢?

为了弄精通,我们查阅了逐一国家所在领域的平分得分。总结平均得分前大家又为每个领域制订了打分标准(通过从各种分数减去平均值,然后除以标准差,也称为z分数),这样的话,即便每个领域的难度有出入,但我们也能对两样世界的个人打分,并摇身一变从总体到个体的可比系统。为了让结果更直观,大家遵照z 分数框架的原理,做了一个 1-100 分数框架来表达。

大家总计了 HackerRank 上程序员最多的 50 个国家,得出下边这张表单:
数学 3
出于中国的程序员得分最高,所以将中华的分数作为 100
的基准分,则俄罗丝的分数为 99.9 ,两国仅相距 0.01 。此外,波兰和瑞士联邦也以
98 的高分进入前列。巴基斯坦得分仅为 57.4 。

印度和米国为全世界贡献了最多的程序员,但未曾进来榜单的前 25名 ,只分级以
76 和 78 的分数名次 31 和 28 。

五、后来的想法

 

当我写出地方的代码时,我感觉到完全可以矢口否认“用 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或上述版本,以上代码没有利用java8函数式编程的新特色。 

若果您接触过java8,请考虑怎么改写以上代码,使其更简洁。

 

2、特定领域名次

虽然中国的名次很典型,但也不只是雄霸所有榜单。哪个国家的程序员在特定领域的表现最好?我们来看望各类领域中上榜的国度。
数学 4
可以看出中国在部分领域十分不错。中国程序员在在数据结构、数学和函数式编程方面制服了此外国家的程序员。此外,俄罗丝(Rose)程序员在挑衅举行最多的算法领域也摘得桂冠。其次是各自处于第二、第三职务的波兰和中国。

怎么解释不同国家在不同领域的档次距离?有可能是因为俄Rose的程序员更欣赏参预算法类的比赛,也就会在这一天地投入更多精力,而大多数华夏程序员则更爱好涉足数据结构类的类型。

在HackerRank工作的一个软件工程师就是如此的,他叫Shimi
Zhang,是我们函数型编程领域排行前十位的程序员之一。他来自华夏菲尼克(Nick)斯市,两年前赶到美利坚联邦合众国念书总结机科学研究生,然后来到HackerRank工作。

发源中国的极品程序员Shimi
Zhang就中国程序员的非凡之处表明了她的视角:

“和其他国家对待,中国的高等教育资源相比较少,中国的青年学习编程的路本来就窄。很多了不起的青少年在收获来之不易的变成竞技,会真正痴迷于此。

在神州,很多小伙在中学时代就开头自学编程了,甚至还品尝解决的有的在全世界也从没多少人能缓解的难题。

开办专门针对青少年工程师的全国性比赛,如 NOIp (
全国青少年音讯学奥林匹克联赛)和 NOI (
全国青年音信学奥林匹克比赛),2019年最少有 3 个人在 NOI
中并且取得了冠军。这种针对青少年举办的编程比赛是近十年内的大方向。

而且, NOI 中还有一个牛逼的特别规定:要是一位选手在 NIO
中获取了金牌,他就不可能出席国际信息学奥林匹克比赛的中国队接纳赛,这就象征,在国际信息学奥林匹克竞技中取得金牌的中原运动员,都是首战告捷。”

六、最终的想法

 

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也可以非凡简洁地实现求导,并不比开头的那段python代码麻烦很多。

 

3、不同国度程序员的宠幸

接下去,我们又相比了各样国家程序员在不同挑衅赛上消费的刻钟,然后与HackerRank用户平均花费的时长举行相比。这样一来,就能找出不同国度程序员在特定领域的偏好了。
数学 5
如上表所示,中国程序员在数学竞技中的出席度远远不止我们预料的平均水平,那就能诠释为啥他们能在这个领域高踞第一名了。捷克人相像很喜爱
shell,在那个单项他们是率先。

七、编程范式

 

在我看来,编程范式简易的话就是编程的一种情势,一种风格。

本人先介绍其中的两个,你基本上就领悟它的意思了。

 

4、不同国家程序员的编程语言偏好

唯独除了这多少个国家,其余国家的采取偏好和擅长领域接近并从未必然联系。我们也想精晓其他国家的程序员对一定的编程语言是否有异样嗜好。比如印度程序员是不是对C++更感兴趣?墨西哥程序员是不是都用Ruby编码?
数学 6

总的来说,世界各地的程序员选择 Java
的比例都要压倒其它语言(唯有极个此外不等:如大马和巴基斯坦的程序员更爱好
C++,黑龙江的程序员更欣赏 Python
)。而斯里兰卡程序员也是JAVA比例使用最高的国家,在HackerRan中也排行排在第八的职务。

巴基斯坦、斯里兰卡和尼日利Adam下名次位居低端,他们可以学学深造瑞士联邦的恒心。程序员在HackerRank社区上从不使劲就摒弃了挑战,得分为零。瑞士的零记分用户比例是最低,瑞士联邦程序员也可谓称得上世界上最顽强的程序员。

事实上对于世界各地的程序员来说,无论你来自何处,都有可能变为一下个盖茨或者克努特。

遵照这多少个多少,假若我们设置一场黑客奥林匹克比赛,中国将收获金牌,俄Rose将取得银牌,而波兰则砍下铜牌。尽管美利哥和印度的程序员令人值得表扬,但想进去前25,依然需要再持续全力的。

翻译的情节相比较多,如有部分语句措辞不当的,欢迎提出。

原稿出处:https://blog.hackerrank.com/which-country-would-win-in-the-programming-olympics/

数学 7

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

探望此间的同班应该对面向对象有了更直观的认识。在面向对象编程中,万物皆对象,抽象出类的定义。基本特征是包裹、继承、多态,认识不深的同学能够再去自己事先的代码中找找这六个特点。

自我事先还介绍了面向对象的多少个标准化:开闭原则依靠反转原则。其他还有单一任务规范里氏替换原则接口隔离原则。这是面向对象的5个主题原则,合称SOLID)。

 

7.2 函数编程语言(FP)

正文起初这段代码用的就是python函数式编程的语法,后来自我又用java8函数式编程的语法翻译了这段代码。

深信不疑你早已直观地感受到它的洗练,以函数为主干,几行代码就解决了求导的问题。

 

7.3 过程式编程(Procedural programming)

大体学过编程都学过C,C语言就是一种过程式编程语言。在我看来,过程式编程大概就是为着成功一个需求,像记流水帐一样,平铺直叙下去。 

       

八、结尾

 

鉴于自家初学java,如今只能想到这样多。假使大家有更好的想法仍旧觉的本身上边说的有题目,欢迎评论,望各位不吝赐教。

这是我的首先篇技术博客,但愿自己表明白了面向对象。假如对您有帮助,请点个赞或者评论下,给自身点持续创作的重力。

相关文章

No Comments, Be The First!
近期评论
    分类目录
    功能
    网站地图xml地图