- 大话编程
- 一个故事讲完 https
- C 老头和 Java 小子的硬盘夜话
- 我是一个函数
- 操作系统是个大骗子?
- 90 后 老头儿 和 00 后 Go 小子的硬盘夜话
- 爱炫耀的数据库老头儿
- 浏览器:一个家族的奋斗
- 浏览器家族的安全反击战
- 黑客三兄弟
- 从读写分离到 CQRS,张大胖是如何解决性能问题的?
- 两个程序的爱情故事
- 两个程序的爱情故事(续)
- 烂代码传奇
- 机房夜话
- 干掉状态:从 session 到 token
- 张大胖的 docker 之路
- 从 SOA 到微服务
- XML 的传奇人生
- 从密码到 token, 一个授权的故事
- 编程世界的那把锁
- 加锁还是不加锁,这是一个问题
- 这个动物园, 两年也逛不完
- 张大胖和 CAP 定理
- 一个翻译家族的发家史
- 张大胖和单元测试
- Java 帝国
- 一个著名的日志系统是怎么设计出来的?
- Java 帝国之泛型
- Java 帝国之动态代理
- 从兄弟到父子:动态代理在民间是怎么玩的?
- Java 注解是怎么成功上位的?
- Java EE 要死掉了?
- Java 帝国之宫廷内斗
- Java 帝国之宫廷内斗(2)
- 当世界上只剩下一个 Java 程序员
- 持久化:Java 帝国反击战
- 什么是框架?
- 学习 Java 虚拟机没用? 听听当事人是怎么说的!
- 聊聊 Java 平台上的非 Java 语言
- Java 帝国之消息队列
- Java 帝国之 JMS 的诞生
- Java 帝国之单例设计模式
- 对 Java Inputstream 的一次采访
- ASM: 一个低调成功者的自述
- 序列化: 一个老家伙的咸鱼翻身
- Java IO 的自述
- JDK 先生最近有点烦
- 什么是框架(续)?
- 说 空话,做实事: 谈谈多态
- Kotlin 初体验
- 小白科普
- 小白科普:分布式和集群
- 什么是 Zookeeper?
- 小白科普:悲观锁和乐观锁
- 小白科普:LDAP 有什么用?
- 小白科普:服务那点事儿
- 小白科普:Netty 有什么用?
- 老司机经验
- 后端程序员都做些什么?
- 为什么要学习 HashMap 的底层原理?
- 小心,别被今日头条给困住了!
- 对自己狠一点,开始写作吧
- 开源代码啃不动,不如先定个小目标
- Python 这么简单还用学吗?
- 作为一个有追求的程序员,你应该掌握的七种武器
- 给设计模式说句公道话
- 时间是这么被浪费掉的
- 你真正付出了全部努力了吗?
- 写给初学者:编程的本质
- 在大学期间更应该学习什么?
- 看看 悲催 的码农得学多少东西?
- 学习编程的四兄弟
- 那些年,我后悔没做好的事情
- 我为什么对后端编程情有独钟?
- 当我们在学习编程语言时,我们在学习什么?
- 编程需要多少数学知识?
- 想成为编程高手,一定要学汇编吗?
- 你必须理解的计算机核心概念
- 你的需求是怎么描述的?
- 白话敏捷软件开发
- 人在职场
- 凡事必先骑上虎背,给性格内向的程序员聊几句
- 为什么能力优秀的人当了主管以后反而不行了呢?
- 不想做技术了,还有一条路
- 纪念我最有效率的一次加班
- 书写「简历」时,需要规避的错误。
- 上天还是入地?
- 工作 6 年,半路出家到 CTO
- 只是 Work 还不够,更重要的是 Think
- 我所尊敬的三位女程序员
- 我们向印度人学习什么?
- 你去下家面试,怎么评价你在这家公司做的工作?
写给初学者:编程的本质
俗话说,开卷有益, 前几天又翻了下《计算机程序的构造和解释》,看到一个采用牛顿法求平方根的例子,产生了点新的感想,和大家分享下。
平方根的数学定义是这样的,对于一个数 x , 如果有另外一个数 r, r 大于等于 0 ,并且 r 的平方等于 x , 那 r 就是 x 的平方根。
这个定义描述了平方根的一般性事实,但是这是一个声明性的描述,并没有告诉我们一个具体的计算过程。 假设我们要写一个程序,给定一个数 x , 怎么求得它的平方根呢?
初学者可能会觉得, 我可以写个这样的程序啊:
square_root( x ){
找到一个 r ,确保 r 的平方等于 x
返回 r
}
但是这个函数一点用都没有,只不过把原来的问题给重新描述了一遍而已。
如果有一个这样的编程语言,程序员会非常高兴: 我们可以用声明性的方式来写程序了!只需要告诉计算机说,找到一个 r ,使得 r 的平方等于输入 x 即可。
但是在当前的计算机体系下面, 这是绝对不可能的,计算机是个笨家伙,它只能按照人类的告诉他的指令一步步的工作, 它突出的优势只是运行得比较快而已。
程序员必须要告诉计算机到底该怎么做,怎么去找到那个 r, 第一步怎么做,第二步怎么做。。。。。什么时候结束。
针对于求平方根的例子, 程序员需要找到一个算法,然后把这个算法的步骤和计算过程用计算机语言描述出来,形成计算机指令。
这个计算过程大概长这个样子:
先猜测 r = 1 , 判断 r 的平方和 x 是不是非常接近(例如相差 0.0001)
如果不接近,让 r = (r+x/r) / 2, 继续判断 r 的平方 与 x 是不是非常接近
如果不接近, 继续让 r = (r+x/r)/2 。。。。。
对于 x =2 , 其计算过程如下:
很明显,这是一个逐渐逼近的过程,计算的次数越多,越逼近真正的平方根。
改写为编程语言描述:
请暂停阅读 10 秒钟, 仔细体会上述的计算过程,它和之前声明性描述有什么区别。
一个描述平方根是什么, 另外一个描述求平方根计算机具体怎么做。
无论多么复杂的程序,无论的前端之王 javascript , 还是后端的 java ,无论是面向过程的还是面向对象的,最终的做的同样的事情:把用户描述的需求(通常是声明式的)变成计算机可以理解,可以运算的步骤。
“是什么” 和 “怎么做”之间有着巨大的鸿沟,这个鸿沟就需要程序员的大脑去填补 。 求平方根是个非常单纯的例子,已经有数学家们想好了具体的计算办法, 程序员翻译一下,变成计算机语言就行。
现实中这样的好事儿是不多的, 比如说你们公司要搞个社交化的促销: 用户连续 x 天转发某个活动到朋友圈就可以获得奖品, 转发的有效时间是早上 9 点至晚上 10 点, 同一天转发多次只算一次。
在实现上你首先得记录用户什么时间转发的,然后对转发时间排个序,过滤掉那些无效的转发,计算这些用户的转发时间没有连续性, 连续的天数到了指定的数值没有。 --- 这就不存在现成的算法,程序员需要自己想出计算的步骤,然后用代码实现。
可以看出,这 不需要高深的数学知识 ,就是找到一个合适的算法和数据结构来描述它,这是编程最最基本的能力。
对于小白来说, 通过自学和培训,可能很快学会一个语言的使用, 可是基本能力不加强,早晚要吃亏的。最突出的表现是给他一个很简单的业务,他花了很长时间才写出一个漏洞百出的版本。
随着业务越来越复杂,一个领域的问题会和其他领域的问题交织纠缠在一起,让复杂度大大增加,简单的一个或几个算法和数据结构是搞不定的, 这时候必须得用一些辅助的手段才能解决,比如使用封装、分层、模式、分布式等等, 这是属于另外一个维度的设计能力了, 这种能力和编程语言都没有关系。
初学者完全可以先学会编程语言和框架,先具备工作能力,然后必须加强数据结构和算法的训练,随着经验的积累,慢慢地扩展到设计和架构层面。
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论