为什么 J 短语“(2&*~) 15 7 3 1”生成一个表,为什么是那个特定的表?

发布于 2024-12-04 19:39:24 字数 2674 浏览 0 评论 0原文

(2&*~) 15 7 3 1 

上面是这句话。最后是痕迹和最终结果。我知道这个短语是一个单子,我知道因为〜它有一个左参数和右参数。如果运行“15 7 3 1(2&*) 15 7 3 1”,会发生相同的输出。我还知道右边的表是 2 的 1、3、7、15 的幂,其他条目是它们的基数乘以 2 的幂,但我只是不明白为什么。

与此相关的是,这是来自罗塞塔代码网站上的埃塞俄比亚乘法的一个短语(实际上,这也是我在试图弄清楚这一点时得到的结果)并且 '(1>.<.@-:)^:a:' 是短语。

(1>.<.@-:)^:a: 27
27 13 6 3 1

但 (1>.<.@-:)^: 27 返回其自身的盒装版本,我希望它运行 27 次。

在三个相关问题的最后一个问题上(这些问题都与分解埃塞俄比亚乘法代码有关),完整的代码给出为:

double =:  2&*
halve  =:  %&2           NB.  or the primitive  -:
odd    =:  2&|

ethiop =:  +/@(odd@] # (double~ <@#)) (1>.<.@halve)^:a:

并且可以简单地替换为:

ethiop =:  +/@(2&|@] # (2&*~ <@#)) (1>.<.@-:)^:a:

效果很好!成功了,当我想到有一个在命令行上工作的单子双精度数时,我完全从悬崖上掉了下来:

+: 98
196

并且双精度运算符必须比带有附加常量的双精度运算符更快,也许双精度只是移位,所以我会认为这

ethiop =:  +/@(2&|@] # (+:~ <@#)) (1>.<.@-:)^:a:

会起作用......但事实并非如此。

我尝试过大写、连词等,但没有任何效果,它总是说“域错误”。我开始认为代码依赖于二元调用的 monad 以我不明白的方式创建加倍表。

唯一的好处是 J 动词 odd 与测试奇数无关。

任何人都可以向我解释这些事情,也许可以用英语解释该程序的工作原理吗?不是算法如何工作,而是它如何实现算法。我记得1970年我在玩IBM 1130 APL的时候。这是一个运行8k字的APL解释器,不用说,它是有限的。例如,它有一个滚动但没有成交。解释器分阶段自行进出内存,支持 1130 代码覆盖,它将您的子例程分成组,当一个组调用另一个组时,它将从磁盘加载新组(是的,8k 中的伪交换)。因此,我使用各种方案编写了交易版本,并且随机地,我们会找到一个可以在不进行搜索的情况下逐步进入和退出的版本,而该版本,无论写得多么糟糕,有多少行和多少解释器操作都会运行 10 次和其他人一样快。我不知道自己在做什么,我会不断添加杂乱和无意义的作业,并跨行破坏语句或将它们组合起来,直到我得到一个无需查找即可运行的语句。 (正在寻找的 52 交易 52 可能需要 45 秒)。

然后昨晚我在J中计算了第150,000个斐波那契数。它必须是64位版本,花了1小时17分钟。我用的是精确算术,这个数字有31349位,它从1012838344936638038开始……我意识到1130永远无法计算出这个,这个数字不合适,因为你需要三个,然后制作最大的一个有 32k 16 位字。我想学习可以做到这一点的语言,但是文档中缺少一些我没有得到的东西。

 trace '(2&*) 15 7 3 1' 
 --------------- 4 Conj -------
 2
 &
 *
 2&*
 --------------- 3 Adverb -----
 2&*
 ~
 2&*~
 --------------- 8 Paren ------
 (
 2&*~
 )
 2&*~
 --------------- 0 Monad ------
 2&*~
 15 7 3 1
 491520 229376 98304 32768
   1920    896   384   128
    120     56    24     8
     30     14     6     2
 ==============================
 491520 229376 98304 32768
   1920    896   384   128
    120     56    24     8
     30     14     6     2

斐波那契脚注:

]t150k=:6!:2 'a150k =: $ ":r150k=: {:  (,+/@(_2&{.) )^:150000 (0x 1x)'
4631.62

0 60 60 #: t150k
1 17 11.6167
r150k
10128383449366380384728502706681008427227914006240871521944866167854579423510169
50198752571599303492471943589300904953648270811064370506598260395645679940891823
17307901573781852234222080308236027906733606532470814177610613237408102006595571
1949713927351702...
a150k
31349
(2&*~) 15 7 3 1 

Above is the phrase. At the end is the trace and the final outcome. I understand that the phrase is a monad, I understand that because of ~ it has a left and right argument. The same output happens if you run '15 7 3 1(2&*) 15 7 3 1'. I also get that the right table are powers of 2 to the 1, 3, 7, 15, and the other entries are their base number times that power of 2, but I just do not understand why.

On a related note, this is a phrase from ethopian multiplication on the Rosetta Code website (actually this is, as well, I got this far in trying to figure that out) and
'(1>.<.@-:)^:a:' is the phrase.

(1>.<.@-:)^:a: 27
27 13 6 3 1

but
(1>.<.@-:)^: 27 returns a box'd version of itself and I would expect it to run 27 times.

On a final of three related questions, (these are all related to decomposing the ethopian multiplication code), the complete code is given as:

double =:  2&*
halve  =:  %&2           NB.  or the primitive  -:
odd    =:  2&|

ethiop =:  +/@(odd@] # (double~ <@#)) (1>.<.@halve)^:a:

and that can be trivially substituted as:

ethiop =:  +/@(2&|@] # (2&*~ <@#)) (1>.<.@-:)^:a:

And that works fine! Flushed with success, I fell completely off of the cliff when I thought, there is a monadic double that works on the command line:

+: 98
196

And a double operator has to be faster than a double with an attached constant, maybe double just shifts, so I would think that

ethiop =:  +/@(2&|@] # (+:~ <@#)) (1>.<.@-:)^:a:

Would work...but it does not.

I have tried caps, conjunctions, and so forth, and nothing gets it to work, it always says, "domain error". I am beginning to think that the code depends on the dyadically called monad to create the doubling table in a way I do not get.

The only good thing is that the J verb odd has nothing to do with testing for an odd number.

Can anyone explain these things to me, maybe with an English explanation of how the program works? Not how the algorithm works, how it implements the algorithm. I recall when I was playing with IBM 1130 APL back in 1970. This was an APL interpreter that ran in 8k words, needless to say, it was limited. For example, it had a roll but no deal. The interpreter phased itself in and out of memory, the 1130 supported code overlays, it would separate your subroutines into groups and when one group called another, it would load the new group off of disk (yes, pseudo swapping in 8k). So I wrote versions of deal, using various schemes, and randomly, we would hit one that could phase in and out without seeking, and that version, no matter how badly written with how many lines and how many interpreter actions would run 10 times as fast as any other. I had no idea what I was doing, I would keep adding ravels and meaningless assignments and breaking statements across lines or combining them until I got one that would run without seeking. (A 52 deal 52 that was seeking could take 45 seconds).

And then last night I calculated the 150,000th Fibonacci number in J. It had to be the 64 bit version, and it took one hour, 17 minutes. I used exact arithmetic, the number has 31349 digits and it starts 1012838344936638038...... And I realized that the 1130 could never have calculated this, the number would not have fit, cause you need three of them and the biggest one made had 32k 16 bit words. I want to learn the language that can do this, but there is something missing from the doc that I am just not getting.

 trace '(2&*) 15 7 3 1' 
 --------------- 4 Conj -------
 2
 &
 *
 2&*
 --------------- 3 Adverb -----
 2&*
 ~
 2&*~
 --------------- 8 Paren ------
 (
 2&*~
 )
 2&*~
 --------------- 0 Monad ------
 2&*~
 15 7 3 1
 491520 229376 98304 32768
   1920    896   384   128
    120     56    24     8
     30     14     6     2
 ==============================
 491520 229376 98304 32768
   1920    896   384   128
    120     56    24     8
     30     14     6     2

Fibonacci Footnote:

]t150k=:6!:2 'a150k =: $ ":r150k=: {:  (,+/@(_2&{.) )^:150000 (0x 1x)'
4631.62

0 60 60 #: t150k
1 17 11.6167
r150k
10128383449366380384728502706681008427227914006240871521944866167854579423510169
50198752571599303492471943589300904953648270811064370506598260395645679940891823
17307901573781852234222080308236027906733606532470814177610613237408102006595571
1949713927351702...
a150k
31349

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

只是偏爱你 2024-12-11 19:39:24

答案记录在 Bond (&) 下其中以下标识用于二元使用:

x m&vy ↔ m&v^:x y

在您的示例中,m 是 2,v 是*,x 和 y 都是四个数字 15 7 3 1 的列表。

等式右侧的措辞包括 ^:x(“x 次方”),这与采用动词并应用 x 次相同。动词是 2&* 因此它被应用了十五次。还有七次。而且还三遍。而且还有一次。这四个应用程序的结果构成了输出的四行。

关注第三个并使用括号强调,这就是发生的事情。

   (2&* (2&* (2&* (15 7 3 1))))
  120 56 24 8

与 相同 与

   (2&*)^:3 (15 7 3 1)
120 56 24 8

相同

   (3) 2&* (15 7 3 1)
120 56 24 8

让我们应用 3 之前的所有非负整数来查看一个模式:

   (0 1 2 3) 2&* (15 7 3 1)
 15  7  3 1
 30 14  6 2
 60 28 12 4
120 56 24 8

此时,与原始表的相似性可能使该表的含义易于理解:

   (15 7 3 1) 2&* (15 7 3 1)
491520 229376 98304 32768
  1920    896   384   128
   120     56    24     8
    30     14     6     2

同样的事情正在发生,它是只是因为您给出了更高的数字而更频繁地发生。

The answer is documented under Bond (&) where the following identity is noted for dyadic use:

x m&v y ↔ m&v^:x y

In your example m is 2, v is *, and both x and y are the list of four numbers 15 7 3 1 .

The phrasing on the right-hand side of the equality includes ^:x ("to the power x") which is the same as taking the verb and applying it x times. The verb is 2&* so it is applied fifteen times. And also seven times. And also three times. And also once. The results of those four applications make up the four rows of the output.

Focusing on the third one and using parentheses for emphasis, here's what's happening.

   (2&* (2&* (2&* (15 7 3 1))))
  120 56 24 8

which is the same as

   (2&*)^:3 (15 7 3 1)
120 56 24 8

which is the same as

   (3) 2&* (15 7 3 1)
120 56 24 8

Let's apply all the non-negative integers through 3 to see a pattern:

   (0 1 2 3) 2&* (15 7 3 1)
 15  7  3 1
 30 14  6 2
 60 28 12 4
120 56 24 8

At this point the similarity to your original table may make the meaning of that table accessible:

   (15 7 3 1) 2&* (15 7 3 1)
491520 229376 98304 32768
  1920    896   384   128
   120     56    24     8
    30     14     6     2

The same thing is happening, it's just happening more often because you've given some higher numbers.

南街九尾狐 2024-12-11 19:39:24

这只是对您的问题的初步尝试,因为到目前为止没有人回复:

副词早已离开范围:

(2&*~) <-> ((2&*)~)

键返回的函数的二元情况是供电

(x m&v y) <-> ((m&v)^:x y)

2&* 每次应用时都会将其参数加倍,因此幂 2&* 会将其参数乘以 2 的幂。

(1>.<.@-:)^: 27 定义一个动词(因为 ^: 是一个连词),但不运行它。在原始短语中,foo^:a: 是动词,27 是参数。当 a:^: 的正确参数时,它只会运行直到收敛。

Monadic +: 将其参数加倍,但 2&*+: 的二元情况没有任何关联,并且可以'不可互换。请注意,double~ 是钩子的左侧,总是以二元方式调用。

唯一的好处是 J 动词 odd 与测试奇数无关。

实际上,2&|如果 y 是奇数,则 y1,如果是偶数,则为 0,因此它是奇数的测试数字。

现在,为了尝试用简单的英语解释该算法在做什么,让我们逐个短语地看它,以 12 ethiop 27 为例:

+/@(2&|@] # (2&*~ <@#)) (1>.<.@-:)^:a:

是一个钩子。在 hooks 中,右侧部分始终是单子,左侧部分始终是二元体。

(1 >. (<. @ -:)) ^: a:

Monad (<. @ -:) = floor @ half将其参数减半并向下舍入,然后 1 > 。 (<.@ -: 返回该值和 1 中的最小值。^:a: 继续下去,直到收敛并列出结果。因此(1 >. (<. @ -:)) ^: a: 2727 重复减半,直到达到 1,产生<代码>27 13 6 3 1

现在让我们看看钩子的左半部分 (2&|@] # (2&*~ <@#)) 是一个二元叉,参数为 ethiop 的左侧参数和上述钩子右侧部分的结果为 1

如果右侧参数为,则 奇怪的, 0 否则,对于参数 27 13 6 3 1,结果为 1 1 0 1 1

(2&*~ @#) 又是一个钩子,<@# 单一地应用于 27 13 6 3 1,并对长度进行装箱,返回。 (<5) 然后我们到达 2&*~,正如我们所见,它是在二元中通电的,所以这是(在 ~< 之后) /code> 切换参数)+:^:(<5) 12

f^:m,当 m 被装箱时,执行 f <: >m 次,产生一个m - 长度的结果列表(除非m 为空,在这种情况下它将运行直到收敛)。所以这将产生 12 * 2 ^ i.5

那么分叉的中间部分就是简单的 #,它带有一个布尔左参数,只是过滤它的右参数,在这个情况下剩下 12 * 2 的幂,其中 27 是奇数。

   1 1 0 1 1 # 12 24 48 96 192
12 24 96 192

最后+/sum

   +/12 24 96 192
324

This is just an initial stab at your questions, since nobody has replied so far:

Adverbs have long left scope:

(2&*~) <-> ((2&*)~)

The dyadic case of the function returned by bond is powered:

(x m&v y) <-> ((m&v)^:x y)

2&* doubles its argument every time it's applied, so powered 2&* multiplies its argument by a power of 2.

(1>.<.@-:)^: 27 defines a verb (since ^: is a conjunction), but does not run it. In the original phrase foo^:a: was the verb, and 27 the argument. When a: is the right argument of ^: it just runs until it converges.

Monadic +: doubles its argument, but the dyadic cases of 2&* and +: aren't related in any way, and can't be interchanged. Note that double~ is the left side of a hook, which is always called dyadically.

The only good thing is that the J verb odd has nothing to do with testing for an odd number.

Actually, 2&| y is 1 if y is an odd integer and 0 if it is an even integer, so it is a test for odd numbers.

Now, to try to explain what the algorithm is doing in plain English, let's look at it phrase by phrase, using 12 ethiop 27 as an example:

+/@(2&|@] # (2&*~ <@#)) (1>.<.@-:)^:a:

is a hook. In hooks the right part is always a monad and the left part is always a dyad.

(1 >. (<. @ -:)) ^: a:

Monad (<. @ -:) = floor @ half, halves its argument and rounds down, and then 1 >. (<. @ -: returns the minimum of that and 1. ^:a: keeps going until convergence and makes a list of the result. Thus (1 >. (<. @ -:)) ^: a: 27 is 27 halved repeatedly until it reaches 1, yielding 27 13 6 3 1

Now let's look at the left half of the hook. (2&|@] # (2&*~ <@#)) is a dyadic fork, with the arguments being the left argument to ethiop and the result of the right part of the aforementioned hook.

2&|@] is 1 if its right argument is odd, 0 otherwise. For the argument 27 13 6 3 1 the result is 1 1 0 1 1

(2&*~ <@#) is a hook again. <@# is applied monadically to 27 13 6 3 1, and boxes the length, returning (<5). Then we get to 2&*~, which as we saw, is powered in the dyadic, so this is (after ~ switches the arguments) +:^:(<5) 12.

f^:m, when m is boxed, does f <: >m times, yielding an m-length list of results (unless m is empty, in which case it runs until convergence). So this will yield 12 * 2 ^ i.5

Then the middle part of the fork is simply #, which with a boolean left argument simply filters its right argument, in this case leaving 12 * those powers of 2 for which 27 is odd.

   1 1 0 1 1 # 12 24 48 96 192
12 24 96 192

Finally +/ is sum

   +/12 24 96 192
324
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文