j 代码来截断无关紧要的数字
j code to Chop insignificant digits
我看到了这段J代码
(**+)&.+.
在 RosettaCode FFT 部分。它应该清理 FFT 结果的微不足道的数字。例如
(**+)&.+。 4e_16j2
给予
0j2
例如类似于Mathematica的Chop
函数。
但是
(**+)&.+. _4j_2
给予
4j2 (instead of _4j_2)
这显然是不正确的。
问题是 J 中切掉无关紧要数字的正确方法是什么?
monad +
(相对于 dyad +
)是“complex conjugate”,这是产生 4j2
而不是 _4j_2
.
RosettaCode 上负责 (**+)&.+.
的编辑可能打算使用 |
、absolute value 代替 +
,因此:
(**|)&.+. _4j_2 4e_16j2
_4j_2 0j2
"numeric" 包中的 round
是 [ * [: <. 0.5 + %~
。您可以按如下方式使用它:
require 'numeric'
(0.01&round)&.+. _1.5j_4.6 4e_16j2 2j4e_16
_1.5j_4.6 0j2 2
问题中给出的代码,更正为使用 |
而不是 +
是 (**|)&.+.
并且它使用对数字进行舍入操作的副产品。您正在获取复数 (&.+.
) 的每个部分并将其绝对值 (|
) 乘以 (*
) 的符号 (*
)。你可以通过用 10j10 -~ 10j10 + ]
.
之类的东西从你的数字中添加和减去一个常量来达到同样的效果
[ * [: <. 0.5 + %~
不使用任何副产品,而是直接将数字四舍五入到所需的精度。 %~
将 y
除以 x
,因此,如果您将 0.3579 四舍五入到小数点后两位(由 0.01 的 x
表示),您的第一步将得到 35.79。然后加上 0.5 (0.5 +
) 并取底数 ([: <.
),这与四舍五入到零位相同(35.79 + 0.5 = 36.29,底数为 36)。最后一步是乘以 x
([ *
) 以撤消对 %~
.
所做的操作
虽然很想用 [ * [: <. 0.5j0.5 + %~
创建 round
的复数版本,但在复数上使用 <.
会产生 complex floor,这可能不是你在追求什么。如果您希望虚部和实部独立舍入,请在 +.
下应用 round
。我认为以下内容可以让您领略到复数的底数与取复数的每一部分的底数有何不同:
<. 0.7 0j0.7 0.6j0.7 0.7j0.6
0 0 0j1 1
这有助于解释以下内容:
1 ([ * [: <. 0.5j0.5 + %~) 0.2 0j0.2 0.1j0.2 0.2j0.1
1 0j1 0j1 1
"Rounding"0.2
到1
让我措手不及,但这是因为0.2 + 0.5i0.5
=0.7i0.5
,而<. 07j0.5
有1
的复杂楼层。 0j0.2
"rounding" 到 0j1
.
也是如此
如果你只想要复数两部分都是整数的最接近的数,你可以使用([: <. 0.5 + ])&.+.
:
([: <. 0.5 + ])&.+. 0.2 0j0.2 0.1j0.2 0.2j0.1
0 0 0 0
([: <. 0.5 + ])&.+. 0.7 0j0.7 0.6j0.7 0.7j0.6
1 0j1 1j1 1j1
我用的(**@|)
没有这个问题
特别是在这种情况下,这似乎可以满足您的要求:
(**@|)&.+.
我看到了这段J代码
(**+)&.+.
在 RosettaCode FFT 部分。它应该清理 FFT 结果的微不足道的数字。例如
(**+)&.+。 4e_16j2
给予
0j2
例如类似于Mathematica的Chop
函数。
但是
(**+)&.+. _4j_2
给予
4j2 (instead of _4j_2)
这显然是不正确的。
问题是 J 中切掉无关紧要数字的正确方法是什么?
monad +
(相对于 dyad +
)是“complex conjugate”,这是产生 4j2
而不是 _4j_2
.
RosettaCode 上负责 (**+)&.+.
的编辑可能打算使用 |
、absolute value 代替 +
,因此:
(**|)&.+. _4j_2 4e_16j2
_4j_2 0j2
round
是 [ * [: <. 0.5 + %~
。您可以按如下方式使用它:
require 'numeric'
(0.01&round)&.+. _1.5j_4.6 4e_16j2 2j4e_16
_1.5j_4.6 0j2 2
问题中给出的代码,更正为使用 |
而不是 +
是 (**|)&.+.
并且它使用对数字进行舍入操作的副产品。您正在获取复数 (&.+.
) 的每个部分并将其绝对值 (|
) 乘以 (*
) 的符号 (*
)。你可以通过用 10j10 -~ 10j10 + ]
.
[ * [: <. 0.5 + %~
不使用任何副产品,而是直接将数字四舍五入到所需的精度。 %~
将 y
除以 x
,因此,如果您将 0.3579 四舍五入到小数点后两位(由 0.01 的 x
表示),您的第一步将得到 35.79。然后加上 0.5 (0.5 +
) 并取底数 ([: <.
),这与四舍五入到零位相同(35.79 + 0.5 = 36.29,底数为 36)。最后一步是乘以 x
([ *
) 以撤消对 %~
.
虽然很想用 [ * [: <. 0.5j0.5 + %~
创建 round
的复数版本,但在复数上使用 <.
会产生 complex floor,这可能不是你在追求什么。如果您希望虚部和实部独立舍入,请在 +.
下应用 round
。我认为以下内容可以让您领略到复数的底数与取复数的每一部分的底数有何不同:
<. 0.7 0j0.7 0.6j0.7 0.7j0.6
0 0 0j1 1
这有助于解释以下内容:
1 ([ * [: <. 0.5j0.5 + %~) 0.2 0j0.2 0.1j0.2 0.2j0.1
1 0j1 0j1 1
"Rounding"0.2
到1
让我措手不及,但这是因为0.2 + 0.5i0.5
=0.7i0.5
,而<. 07j0.5
有1
的复杂楼层。 0j0.2
"rounding" 到 0j1
.
如果你只想要复数两部分都是整数的最接近的数,你可以使用([: <. 0.5 + ])&.+.
:
([: <. 0.5 + ])&.+. 0.2 0j0.2 0.1j0.2 0.2j0.1
0 0 0 0
([: <. 0.5 + ])&.+. 0.7 0j0.7 0.6j0.7 0.7j0.6
1 0j1 1j1 1j1
我用的(**@|)
没有这个问题
特别是在这种情况下,这似乎可以满足您的要求:
(**@|)&.+.