從文件來看, * 運算子將執行叉積,而 ;* 將執行點積。 我想使用叉積來確定一對已知向量的法向向量,如下所示:
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);