我们是不是太关注于语法而忽略了算法
从启明星数学系统Math说起
最近做了一个数学系统(还没做完),中间使用了不少第三方开源插件,但是发现这些插件基本上都是国外的.
事实上这些插件基本上都使用Javascript开发,也并不会涉及太高深的JS知识,但是,这些插件对算法要求甚高。
(1)数学公式
数学公式使用Latex展示,但是把Latex解析为HTML是非常考验基本功的技术。
(2)SVG画图,看起来简单,但是做起来也不容易,这通常出现在习题里,例如"三角形ABC,D是BC上一点。。。"类似这样的题目
(3)几何图形,包括正弦,余弦,正切,余切,指数,对数,微积分,线性变化,圆,椭圆,双曲线等图形
这种图形适合教学,例如通过图形,很容易让学生知道正弦余弦的效果。
上面这些都是基本功,事实上,他是和语言无挂的。如果JS做不出,那么用NET/JAVA/GO/等仍然很难做出。
这就像使用AutoCAD进行机械制图,AutoCAD只是一个工具,如果你设计不同出图形,那么无论使用何种CAD,还是作不出。
因此,相比语法,算法可能更重要。
语法与算法
语法,这里特指计算机语法,是计算机语言规定的一套规则,不同的语言如Java,NET,甚至Javascript,Typescript都定义了自己的一套语言规则。
要使用该语言,必须符合该语言规则。
算法,是解决一件事情的方法,或者说是一系列解决问题的清晰指令,同样一个问题,可以有不同的方法解决,因此算法有好的算法也有不好的算法。
算法的优劣可以用空间复杂度与时间复杂度来衡量。
软件=语法+算法。一个软件的运行需要“语法+算法”两则缺一不可。
计算机只要三个语法即可
事实上,早期,人们编写程序发现,计算机只要三个流程即可:正常的顺序流程,条件流程和循环流程。
顺序流程比较简单,代码一行一行执行,没什么可说明的。
条件流程就是 if 语句
循环流程就是while语句。
除此以外,其它语句都不是必须的,以.NET为例,其实net还提供了goto语句,但是后来人们发现,goto一方面破坏了程序的可读性,让程序跳来跳去,
一方面goto语句可以使用if和whilte替代,所以,goto使用率极低。
掌握了上面的三个流程,就可以写出程序。
顺序的语句
int a=1; int b=2; int c=a+b
if条件语句
int a=1; int b=2 if(a<b) { //do something2 } else { //do something2 }
white循环语句
int i = 0; int sum = 0; while (i < 10) { sum += i; i++; }
由此,.NET的其它语法都可以由这3个基本规则推导而来。
例如switch基本上是和if等效的
switch (i) { case "1": break; case "2": break; case "3": break; } if(if=="1") { // } if(if=="3") { // } if(if=="4") { // }
而.NET的 foreach也是可以由while语句实现
string[] studens = { "s1","stud2"}; foreach (string stud in studens) { .... } int len=studens.Length; while(i<len) { string stud=studens[i]; i++; }
所以,任何计算机语言都一定会提供if语句和while语句,否则这个语言就无法真正成为计算机语言。
算法是千变万化
和计算机语言相对稳定相比,算法才是千变万化。在计算机教程里,对排序的算法讲解的最多,包括 简单排序、插入排序,快速排序,冒泡排序、希尔排序等
每种排序算法都有优点和确定,例如快速排序虽然快速但是稳定性差, 简单排序效率差但是稳定性强。
这就像“马儿跑的快但是力气小,牛儿力气大但是走的慢”,所以,牛马都有各自的应用场景。
软件竞争力核心在算法
在很多情况下,我们感觉“这个软件好,那个软件不好”很大程度上是由算法决定的,这里的算法不仅仅只是排序那么简单。
对NET进行序列化和反序列化,主要有微软提供的DataContractJsonSerializer类和JavaScriptSerializer类,以及开源社区提供的Newtonsoft.Json(JSON.Net)类。
虽然他们都使用.NET开发,但是能明显感觉Newtonsoft.Json优于微软提供的类。(图片来自yanweidie)
算法是发散思维的
计算机语言是限定思维的,就是你只能使用他定义的语法,但是,算法则是发散思维的。这种发散思维体现的是“解决问题的方法”。
当我们在网页里,双击一个文字时,会自动选择该文字对应的单词,
我相信这背后有微软提供的词库,例如你双击“归纳”的“归”,他会自动选中“归纳”,而不是“妨归”。
但是,在进行svg的操作里,微软并未提供这样的“选中”功能,这就需要我们自己实现“选中对象”
上次看mrdoob实现的方式很简单,创建一个span,设置它鼠标样式为:none,设置它边框为红色,就可以实现下图的效果。
var selection = document.createElement( 'span' ); selection.style.position = 'absolute'; selection.style.display = 'block'; selection.style.outline = 'solid 2px #ff0000'; selection.style.pointerEvents = 'none'; document.body.appendChild( selection );
类似的例子还有很多。
谈一谈Visual Studio的实现
以下内容纯属猜想,我也没找他资料来查证下面的猜想。
Visual Studio号称宇宙开发第一工具,一直很好奇他是怎么实现的,特别是字体变亮,语法提示,效果又准又快。
好在有开源的力量,最早知道的是codemirror,codemirror可以让textarea秒变编辑器。
再配合一些插件,就算非专业人士,也能实现类似部分Visual Studio的效果。
但是,Codemirror太复杂.
所以,又找到了 PrismJS,这是一个轻量级的代码显示工具,
使用prism能让你的代码,在web上显示时,看起来很专业。
很容易看到他提供的源代码,核心还是“正则表达式”。也就是系统预定义了样式,当选中所需序言时,切换对应的样式进行变色。
说起来容易,做起来还是很复杂的。
当然,Visual Stuido的实现肯定比这复杂,例如VS的关键字应该是编译后显示亮度,而不是只靠字面的文字。
虽然leetcode也有算法,可是她只是一个点,不是一条线。
--------------------------------------------------------------
启明星数学系统 http://demo.dotnetcms.org/math,主要是供老师使用的一套系统。