문서에 따르면 * 연산자는 교차곱을 수행하고 ;*는 내적을 수행하는 것처럼 보입니다. 나는 다음과 같이 알려진 벡터 쌍에 대한 벡터 법선을 결정하기 위해 외적을 사용하고 싶습니다.
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)와 같아야 합니다. 벡터 외적에 대한 단순화된 공식을 사용하여 이를 수동으로 구현할 수 있지만 행렬 곱셈을 사용하기 위해 이를 다르게 형식화하는 방법을 아는 사람이 있습니까?
열악한 성능은 놀라운 일이 아닙니다. 부호 조정을 삽입해 주셔서 감사합니다. 무심코 "표지판"을 생략했습니다.
IMO 이것은 "할 수 있다고 해서 반드시 해야 한다는 의미는 아닙니다"가 적용되는 사례 중 하나입니다... {멋지다, 재미있다, 짧다}는 {이해 가능하다, 유지 관리 가능하다, 빠르다}보다 중요하지 않습니다.
@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 벡터에만 관심이 있기 때문에 그것은 나에게 효과적이지만 이것이 내장된 기능이 아니라는 사실에 놀랐습니다. 다른 사람이 그런 방법을 알고 있는지 확인하기 위해 이것을 잠시 열어 두겠습니다.
누군가가 이를 수행하는 영리한 방법을 생각해 내기를 바랍니다. det() 함수는 밀접하게 관련되어 있지만 det(3x3 행렬)을 사용하여 스칼라 값 이상을 반환하는 방법을 이해하지 못합니다. 제 생각에는 det(2x2 sub-matrix)를 세 번 사용할 수 있을 것 같지만, 제 생각에는 간단합니다. xyzzy 접근 방식이 더 간단하고 빠릅니다.
3D 장면의 표면 법선에 사용합니다. JSL이 약간 있습니다. https://community.jmp.com/t5/Uncharted/Custom-Visualization/ba-p/191559 .
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);