[英]Most efficient way to check if two vectors are parallel
給定兩個向量u=(ux,uy,uz)
和v=(vx,vy,vz),
),假設向量是平行的或接近平行的(給定一些閾值),計算上最便宜的方法是什么不規范化?
關於幾乎平行:例如,我們假設一個閾值一直到小數點后第一位,例如,如果它們的叉積為0.01
我們可以放心地假設它們是平行的。 我們可以類似地放寬我們可能要使用的其他方法的條件。
如果首選使用編程語言來回答問題,那么讓我們假設我們想用c ++做到這一點。
簡短的答案: 從理論上講,這根本沒有關系。 實際上:測量它
長答案:
同意三角函數反函數是不可能的,讓我們比較計算最后兩個選項的最有效方法。
由於允許向量幾乎平行,因此需要計算
crossx := uy * vz + uz * vy;
crossy := ...;
crossz := ...;
crossNorm = crossx * crossx + crossy * crossy + crossz * crossz;
其中涉及9個乘法和5個加法。 如果向量(幾乎)是平行的,則crossNorm
應該(幾乎)為零。
但是,正如Baum mit Augen正確指出的那樣,足以檢查crossx
, crossy
和crossz
幾乎為零,將其減少為6個乘法和3個加法,但要付出多達兩次以上的比較的代價。 哪種方法更有效,取決於您的語言詳細信息和“接近”等於的定義-例如,如果幾乎等於意味着fabs(...) < 1E-6
那么只需要做一次即可。
標量積為
scalar = ux * vx + uy * vy + uz * vz;
如果向量(幾乎)平行,則
scalar * scalar
應該(幾乎)相等
(ux * ux + uy * uy + uz * uz) * (vx * vx + vy * vy + vz * vz).
這歸結為10個乘法和6個加法。
這只是以上計算,但有兩個額外的double
除法。 這不會增加任何價值,實際上它可能會引入舍入問題。
兩個選項的雙重運算次數幾乎相同。 如果您真的想知道,可以比較程序集https://godbolt.org/z/nJ9CXl,但對於所有實際用途而言,差異將很小。 實際上,如果僅計算“昂貴”指令( mulsd
, addsd
和subsd
),而比較( ucomisd
)則有五個選項。 但是,再次,如果您必須確切知道,請進行測量!
我認為這是錯誤的
標量= l1 * l2 * cos(r)= ux * vx + uy * vy + uz * vz標量^ 2 =(l1 * l2 * cos(r))^ 2 =(ux * vx + uy * vy + uz * VZ)^ 2
(l1 * l2)^ 2 =(ux * ux + uy * uy + uz * uz)*(vx * vx + vy * vy + vz * vz)所以cos(x)^ 2 =標量^ 2 /(ux * ux + uy * uy + uz * uz)*(vx * vx + vy * vy + vz * vz)=(ux * vx + uy * vy + uz * vz)^ 2 / /(ux * ux + uy * uy + uz * uz)*(vx * vx + vy * vy + vz * vz)
當cos為1或-1時x接近0或180,所以cos(x)^ 2-> 1
當這個
福爾米拉(Formila)接近1
(ux * vx + uy * vy + uz * vz)^ 2 /(ux * ux + uy * uy + uz * uz)*(vx * vx + vy * vy + vz * vz)這意味着向量是平行的
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.