我想到一种很自然的解决方法:
把栈表达为 [Base(0), Tail(+), Base(2), Tail(*), Base(3!4!1)] 的形式
然后我们回溯的时候修改一下策略,让它结合 lhs=pop() 就可以了
把栈表达为 [Base(0), Tail(+), Base(2), Tail(*), Base(3!4!1)] 的形式
然后我们回溯的时候修改一下策略,让它结合 lhs=pop() 就可以了
回溯完成,得
每次由归纳程序 reduce 从栈上 pop 出一个项目
如果是 join,则 join 又会从栈上 pop 一个项目,作为 reduce 的 base
不过这样实际上就作了一个断言:栈后面的全是结合性弱的,而且这部分全都是往右结合
我相信这断言是正确的,因为如果有打破它的情况,早就在 stack.mapTop {} 的时候被结合了
2 正确。每次由归纳程序 reduce 从栈上 pop 出一个项目
如果是 join,则 join 又会从栈上 pop 一个项目,作为 reduce 的 base
不过这样实际上就作了一个断言:栈后面的全是结合性弱的,而且这部分全都是往右结合
我相信这断言是正确的,因为如果有打破它的情况,早就在 stack.mapTop {} 的时候被结合了
Calc.kt
4.7 KB
新的,带基于栈的 infix 链扫描算法的 Calc.kt 例子
duangsuse::Echo
Calc.kt
这是上一个,只比它小 1K
现在是愉快的跑分时间~
我将随机生成 5个甚至2 个字符长度的 number,性能优化dssq。
2 个甚至 1 个的空白 ' '
[+-*/!] 里随机选的中缀
重复 5k 个这样的
然后比较两个算法(递归 vs. 显式栈)处理的性能(时间开销)
我将随机生成 5个甚至2 个字符长度的 number,性能优化dssq。
2 个甚至 1 个的空白 ' '
[+-*/!] 里随机选的中缀
重复 5k 个这样的
0 {op whitespace num} 然后比较两个算法(递归 vs. 显式栈)处理的性能(时间开销)
Code:
Launch parse using system stack 14032681694858
= 0
Finish parse using system stack in 14192923ns
Launch parse using ADT stack 14032696090696
= -138278
Finish parse using ADT stack in 1966603ns
好像自动生成的代码很容易 Division by zero…… 管它呢,我不会多做修改的(因为那要维护一个栈……)
结果是完全随机的,不过也很容易理解,就是里面哪怕有一个 *0,结果都是 0。
咱也看到了,的确是有优化的意味呢(迫真)
147KB 的输入,咱的算法足足比原算法快 (14192923-1966603) = 12226320 纳秒
也就是快 0.0122263 秒……
我突然觉得我做的很没意义,emmm
Code: 70395 * 748 - 090 * 984 - 29787 * 959 * 65 * 66 - 083 - 54 / 277 + 00 * 55860 + 7523 ... utf16-size=147KB
Launch parse using system stack 14506658662754
= 0
Finish parse using system stack in 13886095ns
Launch parse using ADT stack 14506672751297
= -1954497720
Finish parse using ADT stack in 2009080ns
第二次测试(在N次失败:栈溢出/Division By Zero后)ADT版依然比递归下降版快 11877015ns
也就是足足快 0.011877s
……在输入足足有147K的情况下
70 - 96991 - 4464 / 0834 * 6187 - 80 * 75 + 18840 ! 1892 ! 77 - 16463 + 008 / 958 * 01 ... utf16-size=147KBLaunch parse using system stack 14032681694858
= 0
Finish parse using system stack in 14192923ns
Launch parse using ADT stack 14032696090696
= -138278
Finish parse using ADT stack in 1966603ns
好像自动生成的代码很容易 Division by zero…… 管它呢,我不会多做修改的(因为那要维护一个栈……)
结果是完全随机的,不过也很容易理解,就是里面哪怕有一个 *0,结果都是 0。
咱也看到了,的确是有优化的意味呢(迫真)
147KB 的输入,咱的算法
也就是快 0.0122263 秒……
我突然觉得我做的很没意义,emmm
Code: 70395 * 748 - 090 * 984 - 29787 * 959 * 65 * 66 - 083 - 54 / 277 + 00 * 55860 + 7523 ... utf16-size=147KB
Launch parse using system stack 14506658662754
= 0
Finish parse using system stack in 13886095ns
Launch parse using ADT stack 14506672751297
= -1954497720
Finish parse using ADT stack in 2009080ns
第二次测试(在N次失败:栈溢出/Division By Zero后)ADT版依然比递归下降版快 11877015ns
也就是
……
不过这是Kotlin/Native的…… 真是
显然这个东西不同平台要有不同实现(Kotlin/multiplatform)
不过因为这里是单线程使用,允许我偷下懒。
显然这个东西不同平台要有不同实现(Kotlin/multiplatform)
不过因为这里是单线程使用,允许我偷下懒。
duangsuse::Echo
Code: 70 - 96991 - 4464 / 0834 * 6187 - 80 * 75 + 18840 ! 1892 ! 77 - 16463 + 008 / 958 * 01 ... utf16-size=147KB Launch parse using system stack 14032681694858 = 0 Finish parse using system stack in 14192923ns Launch parse using ADT stack 14032696090696…
对啊,我怎么没想到这两个版本对相同输入输出都不一样呢?肯定有一个是错的…… 这真是太残酷了
This media is not supported in your browser
VIEW IN TELEGRAM
== summary ==
systemStack: 10 reports
of: 208.887micros, 130.996micros, 49.153micros, 146.203micros, 56.491micros, 47.472micros, 59.137micros, 20.813micros, 21.265micros, 46.551micros
min=20.813micros, max=208.887micros, mean=78.6968micros
AdtStack: 10 reports
of: 1.527514ms, 289.857micros, 71.758micros, 108.715micros, 117.732micros, 111.343micros, 124.688micros, 76.04micros, 48.207micros, 119.849micros
min=48.207micros, max=1.527514ms, mean=259.5703micros
ADT Stack 的性能一点也不比用纯递归的好,艹。
凭什么,难道他们有优化?
而且哪个是正确的?
systemStack: 10 reports
of: 208.887micros, 130.996micros, 49.153micros, 146.203micros, 56.491micros, 47.472micros, 59.137micros, 20.813micros, 21.265micros, 46.551micros
min=20.813micros, max=208.887micros, mean=78.6968micros
AdtStack: 10 reports
of: 1.527514ms, 289.857micros, 71.758micros, 108.715micros, 117.732micros, 111.343micros, 124.688micros, 76.04micros, 48.207micros, 119.849micros
min=48.207micros, max=1.527514ms, mean=259.5703micros
ADT Stack 的性能一点也不比用纯递归的好,艹。
凭什么,难道他们有优化?
而且哪个是正确的?
duangsuse::Echo
== summary == systemStack: 10 reports of: 208.887micros, 130.996micros, 49.153micros, 146.203micros, 56.491micros, 47.472micros, 59.137micros, 20.813micros, 21.265micros, 46.551micros min=20.813micros, max=208.887micros, mean=78.6968micros AdtStack: 10 reports…
This media is not supported in your browser
VIEW IN TELEGRAM
劳资好不容易思考了半天的算法,居然发现性能还不如从前?那我设计它弄啥子,真是岂有此理了。
我要给 Calc.kt 加一个 Lexical Scoping 的功能,然后就可以有『人生第一解释器』啦~