程序员与数学的紧密联系:从Java算法到程序员数学入门

博客:

程序员与数学的紧密联系:从Java算法到程序员数学入门

❝

沉淀、分享、成长,让你和他人有所收获!

❞

目录

4. Java中的算法应用

5. 程序员数学入门

六、总结

7.系列推荐

一、前言

数学离程序员有多近?

无论是ifelse还是for循环,代码都可以说是数理逻辑的具体实现。因此,敲代码的程序员几乎都离不开数学。只是难度不同而已。

那么如果你数学不好就不能写代码吗?不,你仍然可以写代码,写更多的CRUD。然后不要总以为产品需求很简单,所以你的实现过程就变成了增删改查。往往是因为你没有能力实现可扩展、易于维护、高性能的代码实现方案,从而让你显得年轻。多写一点CRUD!

与一锥子买卖货物的小作坊相比,大工厂和超大型工厂会更注重数学能力。

2004年,硅谷交通要道101号公路上突然出现了一块巨大的广告牌,上面写着一道数学题:{e}.com连续数字中的前10个素数。

广告:这里的 e 是一个数学常数,自然对数的底数,无限不循环小数。这题的意思是找到e中出现的前10个素数,然后就可以得到一个网站地址。进入这个网站,你会看到谷歌问你的第二个问题。如果你成功解锁这一步,Google就会告诉你,我们可能是“志同道合”的人。您可以将您的简历发送到此电子邮件地址,让我们一起做一些改变世界的事情。事物。

计算e的值可以由泰勒公式推导出来:e^x≈1 + x + x^2/2! + x^3/3! +...+ x^n/n! (1)推导和计算过程还包括埃拉托斯特尼筛法和线性筛选法的使用。有兴趣的朋友可以用代码来实现。

2. 编写好代码的四个步骤

提出业务需求,制定产品计划,实施研发。最终这个系统的开发是由三方共同决定的!

这里的地基、砖头、水、电、布局分别对应着数据结构、算法逻辑、设计模式、系统架构。从下到上,我们相互依赖,相互协作。只有做好了这一层,才能做好下一层!

所以研发就是承担业务需求,实现产品解决方案。这不仅仅是在三居室或四居室的房子里随机放置砖块。

没有合理的数据结构,没有优化的算法逻辑,没有应用设计模式,整个系统架构最终会变得臃肿、混乱。未来随着需求的追加、迭代、新的需求,整个系统的问题将会不断放大。当你想使用重构时,就有千丝万缕的联系。重构不如重写!

3. for循环不如算法快

《编程之美》一书中,有这样一个问题。求:1~n中1出现的次数。例如:1~10,1出现两次。

1.for循环实现

long startTime = System.currentTimeMillis();
int count = 0;
for (int i = 1; i <= 10000000; i++) {
    String str = String.valueOf(i);
    for (int j = 0; j < str.length(); j++) {
        if (str.charAt(j) == 49) {
            count++;
        }
    }
}
System.out.println("1的个数:" + count);
System.out.println("计算耗时:" + (System.currentTimeMillis() - startTime) + "毫秒");

使用for循环的实现过程很容易理解,就是循环至死。之后根据字符串对循环的数字进行拆解,判断每一位是否是数字,是则+1。过程简单,但时间复杂度较高。

2.算法逻辑实现

如图20-3所示,我们实际上可以发现,1的出现次数是在100、1000、10000之间有规律的循环。11、12、13、14或21、31、41、51,以及单个1出现。最后可以得到通式:abcd...=(abc+1)*1+(ab+1)*10+(a+1)*100+(1)*1000...,abcd代表位数。另外,实现过程中还需要考虑小于100的情况,比如98、1232等。

实施过程

long startTime = System.currentTimeMillis();
int num = 10000000, saveNum = 1, countNum = 0, lastNum = 0;
int copyNum = num;
while (num != 0) {
    lastNum = num % 10;
    num /= 10;
    if (lastNum == 0) {
        // 如果是0那么正好是少了一次所以num不加1了
        countNum += num * saveNum;
    } else if (lastNum == 1) {
        // 如果是1说明当前数内少了一次所以num不加1,而且当前1所在位置
        // 有1的个数,就是去除当前1最高位,剩下位数,的个数。
        countNum += num * saveNum + copyNum % saveNum + 1;
    } else {
        // 如果非1非0.直接用公式计算
        // abcd...=(abc+1)*1+(ab+1)*10+(a+1)*100+(1)*1000...
        countNum += (num + 1) * saveNum;
    }
    saveNum *= 10;
}
System.out.println("1的个数:" + countNum);
System.out.println("计算耗时:" + (System.currentTimeMillis() - startTime) + "毫秒");

这并不是《编程之美》书中唯一的算法。有兴趣的朋友可以去看看。但当你亲自体会后,兴奋感更加强烈!

3、耗时曲线对比

根据两种不同方法的实现逻辑,我们分别计算1000、10000、10000到1亿,找出1出现的次数,看看两种方法的耗时曲线。

那么,您的代码中是否有类似的内容?如果算法逻辑配合合适的数据结构,是否可以替代一些for循环的计算方式,降低整个实现过程的时间复杂度。

4. Java中的算法应用

Java的JDK实现中用到了很多数学知识,包括数组、链表、红黑树的数据结构,以及对应的实现类ArrayList、Linkedlist、HashMap等,当你深入了解这些类的实现时,你会发现他们其实是用代码来实现数学逻辑的。就像你使用数学公式来计算数学问题一样

接下来,付哥就给大家介绍一下我们代码中隐藏的一些数学知识。

1.HashMap的扰动函数

未使用扰动函数

使用的扰动函数

扰动函数的代码

static final int hash(Object key) {
    int h;
    return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16);
}

2. 斐波那契哈希

3. 梅森扭转器

// Initializes mt[N] with a simple integer seed. This method is
// required as part of the Mersenne Twister algorithm but need
// not be made public.
private final void setSeed(int seed) {
    // Annoying runtime check for initialisation of internal data
    // caused by java.util.Random invoking setSeed() during init.
    // This is unavoidable because no fields in our instance will
    // have been initialised at this point, not even if the code
    // were placed at the declaration of the member variable.
    if (mt == null) mt = new int[N];
    // ---- Begin Mersenne Twister Algorithm ----
    mt[0] = seed;
    for (mti = 1; mti < N; mti++) {
        mt[mti] = (MAGIC_FACTOR1 * (mt[mti-1] ^ (mt[mti-1] >>> 30)) + mti);
    }
    // ---- End Mersenne Twister Algorithm ----
}

梅森扭曲器是一种伪随机数生成算法。它由 Makoto Matsumoto 和 Takumi Nishimura 于 1997 年开发,基于有限二元域上的矩阵线性递归。它可以快速生成高质量的伪随机数,纠正经典随机数生成算法的许多缺陷。 Mersenne Twister 最广泛使用的变体之一是 MT19937,它可以生成 32 位整数序列。

5. 程序员数学入门

相比于学习一个较难的知识点的辛苦,那是因为你不知道自己不知道什么!就像我上学时老师说的,不懂就问我。我不知道什么?我该去哪里询问呢?同样的事情!

代码是数理逻辑的实现,简单的逻辑调用关系很容易理解。但当还有一些你可能不知道的数理逻辑时,就很难理解了。例如:扰动函数、负载因子、斐波那契等。这些知识点的学习需要数学知识的验证,否则你只是学了一个概念,死记了一个理论。

当这本书开始使用时,我就会少一些讨厌它。我还是个宝宝啊!

如果你想深入学习程序员应该知道的数学,我推荐技术博主Jeremy Kun,他花了4年时间写了一本《程序员数学入门》一书。

本书为程序员提供了丰富的精简数学知识,包括多项式、集合、图论、群论、微积分和线性代数。同时,wiki部分还包括抽象代数、离散数学、傅立叶分析、拓扑等。

作者说,如果你作为本科生有一定的数学知识,那么这本书相当适合你,不会很难。本书前三章为基础数学内容,后面各章难度逐渐增加。

六、总结

结尾

任正非:希望大家忘记我

学习更多知识,为国家做出贡献!

点击学习

你可能想看:
« 上一篇
下一篇 »

相关推荐

java中什么是冒泡,冒泡算法

2026年09月06日

27阅读

java中冒号,java双冒号

2026年09月06日

26阅读

java中的->,java中的是什么意思

2026年09月06日

24阅读

java中的super用法,Java中super的说明

2026年09月06日

28阅读

java中反射的应用,java中反射的应用场景

2026年09月06日

25阅读

java中开关的定义,Java关键字有哪些

2026年09月06日

25阅读