簡體   English   中英

檢查兩個向量是否平行的最有效方法

[英]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正確指出的那樣,足以檢查crossxcrossycrossz幾乎為零,將其減少為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,但對於所有實際用途而言,差異將很小。 實際上,如果僅計算“昂貴”指令( mulsdaddsdsubsd ),而比較( 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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM