TL;DR
Per 评论 https://stackoverflow.com/questions/26690417/j-tacit-adverb-of-newtons-method#comment42031688_26690417,简短回答;与原始的、显式的默认等价newton_i
and newton
分别是:
n_i =: d.0 1 (%/@:) (]`-`) (`:6)
newton =: n_i (^:_)
一般来说,可以在以下位置找到有关如何获得此类翻译的一些技术:J 论坛 http://www.jsoftware.com/pipermail/programming/2010-November/021172.html.
建造
这里的关键见解是(a)函数与它自己的“零阶导数”相同,并且(b)我们可以同时计算 J 中函数的“零阶”和一阶导数,这要归功于该语言的数组 -导向的性质。剩下的就是集邮了。
在理想世界中,给定一个函数f
,我们想要生成一个动词序列,例如(] - f % f d. 1)
。问题是 J 中的默认状语编程限制我们产生一个提到输入函数的动词(f
)一次且仅一次。
因此,我们使用了一个偷偷摸摸的技巧:我们计算two的衍生物f
同时:“零”导数(这是一个恒等函数)和一阶导数。
load 'trig'
sin NB. Sine function (special case of the "circle functions", o.)
1&o.
sin d. 1 f. NB. First derivative of sine, sin'.
2&o.
sin d. 0 f. NB. "Zeroeth" derivative of sine, i.e. sine.
1&o."0
sin d. 0 1 f. NB. Both, resulting in two outputs.
(1&o. , 2&o.)"0
znfd =: d. 0 1 NB. Packaged up as a re-usable name.
sin znfd f.
(1&o. , 2&o.)"0
然后我们只需在它们之间插入一个除法:
dh =: znfd (%/@) NB. Quotient of first-derivative over 0th-derivattive
sin dh
%/@(sin d.0 1)
sin dh f.
%/@((1&o. , 2&o.)"0)
sin dh 1p1 NB. 0
_1.22465e_16
sin 1p1 NB. sin(pi) = 0
1.22465e_16
sin d. 1 ] 1p1 NB. sin'(pi) = -1
_1
sin dh 1p1 NB. sin(pi)/sin'(pi) = 0/-1 = 0
_1.22465e_16
The (%/@)
来到右侧znfd
因为 J 中的默认状语编程是 LIFO(即从左到右,而“正常”J 是从右到左)。
集邮
正如我所说,剩下的代码只是集邮,使用标准工具构建一个动词序列,从原始输入中减去这个商:
ssub =: (]`-`) (`:6) NB. x - f(x)
+: ssub NB. x - double(x)
] - +:
-: ssub NB. x - halve(x)
] - -:
-: ssub 16 NB. 16 - halve(16)
8
+: ssub 16 NB. 16 - double(16)
_16
*: ssub 16 NB. 16 - square(16)
_240
%: ssub 16 NB. 16 - sqrt(16)
12
Thus:
n_i =: znfd ssub NB. x - f'(x)/f(x)
最后,使用“应用到定点”功能 https://stackoverflow.com/questions/18682404/j-why-does-fproposition-y-stand-for-a-while-loop/18685836#18685836 of ^:_
, 我们有:
newton =: n_i (^:_)
Voila.