做者:小傅哥
博客:https://bugstack.cnhtml
沉淀、分享、成长,让本身和他人都能有所收获!😄java
数学离程序员有多近?
git
ifelse也好、for循环也罢,代码能够说就是对数学逻辑的具体实现。因此敲代码的程序员几乎就离不开数学,难易不一样而已。程序员
那数学很差就写不了代码吗😳?不,同样能够写代码,能够写出更多的CRUD
出来。那你不要总以为是产品需求简单因此你的实现过程才变成了增删改查,每每也是由于你还不具有可扩展、易维护、高性能的代码实现方案落地能力,才使得你小小年纪写出了更多的CRUD
!算法
与一锥子买卖的小做坊相比,大厂和超级大厂更会注重数学能力。数据库
2004年,在硅谷的交通动脉 101 公路上忽然出现一块巨大的广告牌,上面是一道数学题: {e 的连续数字中最早出现的 10 位质数}
.com。编程
广告:这里的 e 是数学常数,天然对数的底数,无限不循环小数。这道题的意思就是,找出 e 中最早出现的 10 位质数,而后能够得出一个网址。进入这个网址会看到 Google 为你出的第二道数学题,成功解锁这步 Google 会告诉你,咱们或许是”志同道合“的人
,你能够将简历发到这个邮箱,咱们一块儿作点改变世界的事情。设计模式
计算 e 值能够经过泰勒公式推导出来:e^x≈1 + x + x^2/2! + x^3/3! +……+ x^n/n! (1) 推导计算过程还包括埃拉托色尼筛选法(the Sieve of Eratosthenes)
、线性筛选法
的使用。感兴趣的小伙伴能够用代码实现下。数组
业务提需求、产品定方案、研发作实现。
最终这个系统开发的怎么样是由三方共同决定的!微信
这里的地基、砖头、水电、格局,对应的就是,数据结构、算法逻辑、设计模式、系统架构。从下到上相互依赖、相互配合,只有这一层作好,下一层才好作!
因此,研发在承接业务需求、实现产品方案的时候。压根就不仅是在一个房子的三居或者四居格局里,开始随意码砖。
没有合理的数据结构、没有优化的算法逻辑、没有运用的设计模式,最终都会影响到整个系统架构变得臃肿不堪,调用混乱。在之后附加、迭代、新增的需求下,会让整个系统问题不断的放大,当你想用重构时,就有着千丝万缕般调用关系。 重构就不如重写了!
在《编程之美》一书中,有这样一道题。求:1n中,1出现的次数。好比:110,1出现了两次。
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。这个过程很简单,可是时间复杂很高。
如图 20-3 所示,其实咱们能发现这个1的个数在100、1000、10000中是有规则的循环出现的。十一、十二、1三、14或者2一、3一、4一、51,以及单个的1出现。最终能够得出通用公式:abcd...=(abc+1)*1+(ab+1)*10+(a+1)*100+(1)*1000...
,abcd表明位数。另外在实现的过程还须要考虑好比不足100等状况,例如9八、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) + "毫秒");
在《编程之美》一书中还不仅这一种算法,感兴趣的小伙伴能够查阅。但本身折腾实现后的兴奋感更强哦!
按照两种不一样方式的实现逻辑,咱们来计算1000、10000、10000到一个亿,求1出现的次数,看看两种方式的耗时曲线。
那么,你的代码中是否也有相似的地方。若是使用算法逻辑配合适合的数据结构,是否能够替代一些for循环的计算方式,来使整个实现过程的时间复杂度下降。
在 Java 的 JDK 实现中有不少数学知识的运用,包括数组、链表、红黑树的数据结构以及相应的实现类ArrayList、Linkedlist、HashMap等。当你深刻的了解这些类的实现后,会发现它们其实就是使用代码来实现数学逻辑而已。就像你使用数学公式来计算数学题同样
接下来小傅哥就给你介绍几个隐藏在咱们代码中的数学知识。
未使用扰动函数
已使用扰动函数
扰动函数公式
static final int hash(Object key) { int h; return (key == null) ? 0 : (h = key.hashCode()) ^ (h >>> 16); }
f(k) = ((k * 2654435769) >> X) << Y对于常见的32位整数而言,也就是 f(k) = (k * 2654435769) >> 28
除法散列法
、平方散列法
、随机数法
等。// 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 ---- }
梅森旋转算法(Mersenne twister)是一个伪随机数发生算法。由松本真和西村拓士在1997年开发,基于有限二进制字段上的矩阵线性递归。能够快速产生高质量的伪随机数,修正了古典随机数发生算法的不少缺陷。 最为普遍使用Mersenne Twister的一种变体是MT19937,能够产生32位整数序列。
与接触到一个有难度的知识点学起来辛苦相比,是本身不知道本身不会什么!就像上学时候老师说,你不会的就问我。我不会啥?我从哪问?同样同样的!
代码是对数学逻辑的实现,简单的逻辑调用关系是很容易看明白的。但还有那部分你可能不知道的数学逻辑时,就很难看懂了。好比:扰动函数、负载因子、斐波那契(Fibonacci)等,这些知识点的学习都须要对数学知识进行验证,不然也就学个概念,背个理论。
书到用时方恨少,在下仍是个宝宝!
那若是你想深刻的学习下程序员应该会的数学,推荐给你一位科技博主 Jeremy Kun 花了4年时间,写成一本书 《程序员数学入门》。
这本书为程序员提供了大量精简后数学知识,包括:多项式、集合、图论、群论、微积分和线性代数等。同时在wiki部分还包括了抽象代数、离散数学、傅里叶分析和拓扑学等。
做者表示,若是你本科学过一些数学知识,那么本书仍是挺适合你的,不会有什么难度。书中的前三章是基础数学内容,日后的难度依次递增。
程序员数学
,下载这本书知识的路上是发现知识的快乐,还学会知识的成就感,不断的促使你前行
。