简而言之
根据评论,简短回答一下;隐含的等价于原始的显式newton_i
和newton
分别是:
n_i =: d.0 1 (%/@:) (]`-`) (`:6)
newton =: n_i (^:_)
一般而言,获取此类翻译的一些技巧可以在J论坛上找到。
构建
关键见解是(a)函数与其自身的“零阶导数”相同,以及(b)由于J语言的数组导向性质,我们可以同时计算一个函数的“零阶”和一阶导数。其余只是简单的收集信息。
在理想情况下,给定一个函数f
,我们希望生成一个动词序列,如(] - f % f d. 1)
。问题在于,J语言中的省略副词编程限制了我们必须生成一个动词,该动词仅一次提及输入函数(f
)。
因此,我们使用一个巧妙的技巧:同时计算两个导数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 (
sin dh
sin dh f.
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
< p >
(%/@)
出现在
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
因此:
n_i =: znfd ssub NB. x - f'(x)/f(x)
最后,使用^:_
的"应用到不动点"功能,我们得到:
newton =: n_i (^:_)
看这里。
d.
会阻止您编写一个暗示的副词。 - Eelvexn_i =: d.0 1 (%/@:) (-\
) (]`) (`:6)和
newton =: n_i (^:_)`。稍后我会回来并解释为什么(我现在正在用手机)。 - Dan Bronf(d.0 1)(%/@:)
视为一个黑盒子,它有效地构建了(f%f d.1)
;那么你就得到了black_box(\
-)(`]),反向阅读(LIFO)后读取
],
-,
black_box,然后执行成为列车
] - black_box。不,真正狡猾的技巧在于使用了
d.0 1` :)。这样清楚了吗?还是需要我发布正式答案? - Dan Bronf (d.0 1) (%/@:)
的技巧 :) - 确实很酷:我们计算f
的零阶和一阶导数,然后在它们之间插入%
。我也理解了你写这三个副词的顺序。非常感谢! - Dan Oak) (]
) (`:6)”,我会接受它。然后我会添加整个解释,就像我理解的那样。 - Dan Oak