为什么 J 短语“(2&*~) 15 7 3 1”生成一个表,为什么是那个特定的表?
(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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
答案记录在 Bond (&) 下其中以下标识用于二元使用:
x m&vy ↔ m&v^:x y
在您的示例中,m 是
2
,v 是*
,x 和 y 都是四个数字15 7 3 1
的列表。等式右侧的措辞包括
^:x
(“x 次方”),这与采用动词并应用 x 次相同。动词是2&*
因此它被应用了十五次。还有七次。而且还三遍。而且还有一次。这四个应用程序的结果构成了输出的四行。关注第三个并使用括号强调,这就是发生的事情。
与 相同 与
相同
让我们应用 3 之前的所有非负整数来查看一个模式:
此时,与原始表的相似性可能使该表的含义易于理解:
同样的事情正在发生,它是只是因为您给出了更高的数字而更频繁地发生。
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 numbers15 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 is2&*
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.
which is the same as
which is the same as
Let's apply all the non-negative integers through 3 to see a pattern:
At this point the similarity to your original table may make the meaning of that table accessible:
The same thing is happening, it's just happening more often because you've given some higher numbers.
这只是对您的问题的初步尝试,因为到目前为止没有人回复:
副词早已离开范围:
键返回的函数的二元情况是供电:
2&* 每次应用时都会将其参数加倍,因此幂
2&*
会将其参数乘以2
的幂。(1>.<.@-:)^: 27
定义一个动词(因为^:
是一个连词),但不运行它。在原始短语中,foo^:a:
是动词,27
是参数。当a:
是^:
的正确参数时,它只会运行直到收敛。Monadic
+:
将其参数加倍,但2&*
和+:
的二元情况没有任何关联,并且可以'不可互换。请注意,double~
是钩子的左侧,总是以二元方式调用。实际上,
2&|如果
为y
是奇数,则 y1
,如果是偶数,则为0
,因此它是奇数的测试数字。现在,为了尝试用简单的英语解释该算法在做什么,让我们逐个短语地看它,以
12 ethiop 27
为例:是一个钩子。在 hooks 中,右侧部分始终是单子,左侧部分始终是二元体。
Monad
(<. @ -:)
=floor @ half
,将其参数减半并向下舍入,然后1 > 。 (<.@ -:
返回该值和1
中的最小值。^:a:
继续下去,直到收敛并列出结果。因此(1 >. (<. @ -:)) ^: a: 27
被27
重复减半,直到达到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 是奇数。最后
+/
是sum
This is just an initial stab at your questions, since nobody has replied so far:
Adverbs have long left scope:
The dyadic case of the function returned by bond is powered:
2&*
doubles its argument every time it's applied, so powered2&*
multiplies its argument by a power of2
.(1>.<.@-:)^: 27
defines a verb (since^:
is a conjunction), but does not run it. In the original phrasefoo^:a:
was the verb, and27
the argument. Whena:
is the right argument of^:
it just runs until it converges.Monadic
+:
doubles its argument, but the dyadic cases of2&*
and+:
aren't related in any way, and can't be interchanged. Note thatdouble~
is the left side of a hook, which is always called dyadically.Actually,
2&| y
is1
ify
is an odd integer and0
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:is a hook. In hooks the right part is always a monad and the left part is always a dyad.
Monad
(<. @ -:)
=floor @ half
, halves its argument and rounds down, and then1 >. (<. @ -:
returns the minimum of that and1
.^:a:
keeps going until convergence and makes a list of the result. Thus(1 >. (<. @ -:)) ^: a: 27
is27
halved repeatedly until it reaches1
, yielding27 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 toethiop
and the result of the right part of the aforementioned hook.2&|@]
is1
if its right argument is odd,0
otherwise. For the argument27 13 6 3 1
the result is1 1 0 1 1
(2&*~ <@#)
is a hook again. <@# is applied monadically to27 13 6 3 1
, and boxes the length, returning(<5)
. Then we get to2&*~
, which as we saw, is powered in the dyadic, so this is (after~
switches the arguments)+:^:(<5) 12
.f^:m
, whenm
is boxed, doesf
<: >m
times, yielding anm
-length list of results (unlessm
is empty, in which case it runs until convergence). So this will yield12 * 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.Finally
+/
issum