我发现在'addons/math/misc/brent.ijs'
实施布伦特的方法作为副词。我想建立一个牛顿方法作为副词,但它比构建默认动词要困难得多。
以下是牛顿迭代的显式版本:
newton_i =: 1 : '] - u % u d.1'
有了这样的用法:
2&o. newton_i^:_ (1) NB. (-: 1p1) must be found
1.5708
2 o. 1.5708 NB. after substitution we get almost 0
_3.67321e_6
当然,为方便起见:
newton =: 1 : 'u newton_i^:_'
什么是默契?
答案 0 :(得分:6)
Per the comments,一个简短的回答;隐含的原始隐私newton_i
和newton
分别为:
n_i =: d.0 1 (%/@:) (]`-`) (`:6)
newton =: n_i (^:_)
有关如何获得此类翻译的一些技巧,通常可以在the J Forums上找到。
这里的关键见解是:(a)一个函数与它自己的"零导数"相同,并且(b)我们可以计算"零"由于语言的数组导向特性,J和J中函数的一阶导数同时存在。剩下的只是集邮。
在一个理想的世界中,给定一个函数f
,我们希望生成像(] - f % f d. 1)
这样的动词训练。问题是J中的默认状语编程限制我们产生一个动词,它只提及一次输入函数(f
)。
所以,相反,我们使用一个偷偷摸摸的技巧:我们同时计算{em>两个衍生物f
:"第0"衍生物(它是一种身份函数)和一阶导数。
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
(%/@)
位于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)
最后,使用^:_
的{{3}},我们有:
newton =: n_i (^:_)
瞧。
答案 1 :(得分:1)
newton_i =: 1 : '] - u % u d.1'
是半默会的,因为当它与动词绑定时会产生默认动词(当绑定时副词消失)。
newton_i2 =: 1 : '(] - u % u d.1) y'
是完全明确的,因为与动词的绑定无法解析副词。
+ 1 : 'u/'
+ /
+ 1 : 'u/ y'
+(1:' u / y')
使半隐性副词完全默契是没有多大意义的,因为可能没有性能提升,并且它具有在副词区域内而不是在调用者中解决的相同好处(完全显式副词的情况)