希望您喜欢挑战 4。如果您将来有想法可以做成一项好的挑战,请告诉我。我一直在寻找好的素材!
恭喜, @landon !在 100 对 1,000 位数字(9.88 秒)和最长数字(7,150)挑战中,您的参赛速度最快(非工作人员)。它不仅是唯一能够在 10 秒内读取所有 100 对 1,000 位数字的脚本(下一个最接近的脚本只能读取 10 对),而且还可以将两个数字相乘,而这两个数字是下一个最接近的脚本的 3.5 倍!此外,它是所有脚本(工作人员和非工作人员)中最短的,只有 1,000 多个字符。我已将其包含在下面的脚本中。四次挑战后的得分总数为:
在讨论大数相乘之前,我们先讨论一下如何解包或矢量化一串数字 - 将一串数字转换为数字矢量。正如我们上个月看到的,使用子串在循环中一次解析一个数字字符串非常慢。这给我们留下了两个常规替代方案:1) 将字符串解构为单个单元,然后将它们重新组合成可以转换为矢量的形式(例如,使用解析 )或 2) 使用模式匹配。我最初倾向于使用方法 1。多年来,我一直拒绝学习 JSL 模式匹配函数。这太费劲了,信息和示例太少,而且我太懒了。我认为正则表达式函数已经满足了我的所有需求,这是我非常熟悉的东西。现在不行了。
这些挑战让我大开眼界,看到了模式匹配的速度和效率。正如这些功能的开发人员和挑战的常客@Craige_Hales向我解释的那样,JSL 中的模式匹配例程是构建正则表达式的基础。为了证明它们的效率,运行矢量化示例.JSL中的代码,它比较了四种不同的矢量化方法。我还在脚本中包含了一个生成长串随机数的短函数。对于一个包含 10,000 个数字的字符串,在循环中一次解析一个数字是迄今为止最慢的,在我的计算机上大约需要 11 秒。使用字和连接列表将数字解构并重构为可以解析为向量的字符串,效果要好得多(0.0965 秒)。
使用正则表达式和解析执行相同的操作效果略好于此(0.08543)。模式匹配将此时间缩短了惊人的 4 倍(0.02179)!虽然 50,000 位数字的时间差异很小,但如果我们考虑 5,000,000 位数字,两种解析方法大约需要 10 分钟,而模式匹配需要 2 秒,与其他方法不同,几乎呈线性扩展!如果您想了解有关 JSL 中模式匹配的更多信息,请查看由@Craige_Hales或@David_Burnham编写的脚本(他有几篇自己的博客文章,其中包含更多信息和示例。)
接下来是乘法例程。所有矢量化都使用模式匹配。此外,第一个示例中使用了上一个挑战中最快的加法算法。第一种方法 ( multiplyBig Slow.JSL ) 没有使用我们迄今为止在挑战中学到的知识以外的任何内容。它每次将两位数字相乘,确保根据被乘数和乘数的位置添加零(例如,当百位数字乘以十位数字时添加五个零)。尽管函数按输入的顺序排列,使第一个输入较大,但这并没有什么好处。执行的操作次数相同。然而,这在最后一个示例中会有所改变。该函数很慢,需要近 30 秒才能处理一组 100 个 100 位数字。
在倍增更快.JSL中,寄存器中的位数从 1 增加到 7,大约是 JSL 可以表示的位数的一半,不会出现溢出。当我们将两个大的七位数字相乘时,这种选择的原因就显而易见了,其结果可能多达十四位。由于七位寄存器可能包含 14 位数字,因此必须更改上一个示例中使用的加法例程,以便将第 7 位以外的任何数字都传送到下一个寄存器。尽管如此,由于只需要考虑正数,因此生成的代码要短得多。此外,将 100 个 100 位数字对相乘的结果(0.04375 秒)也得到了显著改善。此实现在将 100 个 1000 位数字对相乘时(1.54 秒)也做得不错。
只需进行一个简单的更改,您就可以获得更快的速度。 multiplyBig Fastest.JSL不是一次乘以一个寄存器,而是使用 JSL 矩阵运算将每个寄存器中的较短数字与整个较大数字相乘。 这种方法比以前的方法更快,对于 100 个 1,000 位数字对,只需 0.3015 秒,速度提高了 5 倍。
而且,您还可以加快速度。文件multiplyBig – Brady.JSL在乘以 1,000 位数字时速度稍慢,但在数字大小达到约 2,000 位及以上时速度更快。这是通过更改运算顺序来实现的,这样乘法和加法就可以在同一个循环中完成。这背后的细节超出了我的范围,但@brady_brady告诉我,如果有兴趣,他很乐意写一篇简短的文章,我可以将其添加到这篇文章中。更快?也许吧。有两种著名的乘法算法通常用于密码学,它们将乘法运算的数量从 O(n 2 ) 减少到O(n 1.58 )或更低。因为它们需要对大数字进行更多的加法运算,所以很难说它们在 JSL 中是否会更快。截至本文撰写时,我尝试但无法实现这两种算法的快速 JSL 版本。
2020 年 8 月 1 日:感谢@Craige_Hales发现multiplyBig Fastest.JSL中的一个错误。我已经纠正了这个问题。我还添加了 Craige 的 multiplyBig 脚本,我本打算添加但忘记了。他使用查找表来加速算法(但有一些注意事项)。他的脚本像往常一样有详细的注释。