从文档来看, * 运算符将执行叉积,而 ;* 将执行点积。 我想使用叉积来确定一对已知向量的法向向量,如下所示:
p1 = [1, 2, 4];
p2 = [2, 1, 4];
p3 = [2, 2, 4];
v1 = p3 - p1;
v2 = p2 - p1;
xProd = v1*v2;
3 个点定义一个平面,从这些点获取的两个向量做同样的事情,叉积应该给出该平面的法向量。 问题似乎是相乘的两个矩阵(v1 和 v2)的维度不一致 - nRows(v1) 应等于 nCols(v2)。 我可以使用矢量叉积的简化公式手动实现此操作,但有人知道如何以不同的方式格式化它以使用矩阵乘法吗?
性能较差并不令人惊讶......感谢插入符号调整。 我无意中漏掉了“符号棋盘”。
在我看来,这是“仅仅因为你可以,并不意味着你应该”适用的情况之一...... {酷、有趣、简短}并不胜过{可理解、可维护、快速}。
@brady_brady凉爽的! 如果您要使用它,则需要进行调整:
i = 1;
j = -1;
J( 3, 1, (j *= -1) * Det( (v1 || v2)[Remove( [1, 2, 3], i++ ), 0] ) );
</CODE><A href="https://mathinsight.org/cross_product_formula" target="_blank" rel="nofollow noopener noreferrer">https://mathinsight.org/cross_product_formula</A>显示中间元素如何需要为负数。上面,j 将交替符号 (1, -1, 1),i 会增加 (1, 2, 3)。 J(...) 函数有一个隐式循环,用于计算每个元素的第三个参数。</P>
<P> </P>
<P>直接修正的公式为<A href="https://community.jmp.com/t5/user/viewprofilepage/user-id/11962" target="_blank">@klk</A>速度大约提高了 3 倍,并且更容易理解大约 N 倍。</P>
<P> </P>
<P>测试代码。</P>
<DIV class="lia-spoiler-container"><A class="lia-spoiler-link" href="#" rel="nofollow noopener noreferrer" target="_blank">查看更多...</A><NOSCRIPT><DIV class="lia-spoiler-content"><BR /><PRE><CODE class=" language-jsl">v1 = [0, 0, 1];
v2 = [0, 1, 0];
start = HP Time();
For( t = 1, t < 1e6, t += 1,
i = 1;
j = -1;
J( 3, 1, (j *= -1) * Det( (v1 || v2)[Remove( [1, 2, 3], i++ ), 0] ) );
);
stop = HP Time();
Show( (stop - start) / 1e6 );//9.3s
start = HP Time();
For( t = 1, t < 1e6, t += 1,
Matrix( {v1[2] * v2[3] - v1[3] * v2[2], v1[3] * v2[1] - v1[1] * v2[3], v1[1] * v2[2] - v1[2] * v2[1]} )
);
stop = HP Time();
Show( (stop - start) / 1e6 );//3.2s
For( q = 1, q < 10000, q += 1,
v1 = J( 3, 1, Random Uniform( -1, 1 ) );
v2 = J( 3, 1, Random Uniform( -1, 1 ) );
If(
All(
Round( Matrix( {v1[2] * v2[3] - v1[3] * v2[2], v1[3] * v2[1] - v1[1] * v2[3], v1[1] * v2[2] - v1[2] * v2[1]} ), 10 ) //
== //
(i = 1; j = -1 ; Round( J( 3, 1, (j *= -1) * Det( (v1 || v2)[Remove( [1, 2, 3], i++ ), 0] ) ), 10 ) ; ) //
) == 0//
, //
Throw( Char( q ) )
);
);奇怪的是,四舍五入到 11 位有时无法匹配结果。 可能几乎共线向量。
好吧,复活的僵尸抓住了我。 这是一种通过行列式来做到这一点的方法@Craige_Hales提及。 它很短,但我不知道......它不是很简单。
crossP = Function( {x, y, i = 1},
Return( J( 3, 1, Det( (x || y)[Remove( [1, 2, 3], i++ ), 0] ) ) )
);
即,使用最初提供的数据:

很抱歉恢复这个僵尸线程,但是这里的第二个元素有一个符号错误。我相信应该是
Matrix(
{v1[2] * v2[3] - v1[3] * v2[2], v1[3] * v2[1] - v1[1] * v2[3], v1[1] * v2[2] - v1[2] * v2[1]}<BR />)只是想把这个留在这里供其他人快速复制粘贴。
谢谢cwillden,这基本上就是我所实现的。 它确实对我有用,因为我只关心 3D 矢量,但我很惊讶这不是内置函数。 我将把这个问题暂时搁置一下,看看是否有其他人知道这种方法。
如果您只处理 3x1(或 1x3)向量,那么我认为计算效率或优雅并不是太重要。这足够了吗?
cross_prod = function({v1, v2},
matrix({v1[2]*v2[3] - v1[3]*v2[2], v1[1]*v2[3] - v1[3]*v2[1], v1[1]*v2[2] - v1[2]*v2[1]});
);
cross_prod(v1, v2);