给定两个向量u=(ux,uy,uz)
和v=(vx,vy,vz),
,假定向量是并行的或近(给定一些近似值),那么检查它们的计算上最便宜的方法是什么没有规范化?
关于几乎平行:例如,我们假设一个阈值一直到小数点后第一位,例如,如果它们的叉积为0.01
,则可以安全地假定它们是平行的。我们可以类似地放宽我们可能要使用的其他方法的条件。
如果首选使用编程语言来回答问题,让我们假设我们想使用c ++来实现。
答案 0 :(得分:5)
简短答案: 从理论上讲,这根本没有关系。实际上:对其进行测量
长答案:
同意三角函数反函数是不可能的,让我们比较计算最后两个选项的最有效方法。
由于允许向量几乎平行,因此需要计算
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
),则两个选项都有五个。但是,再次提醒您,如果您必须准确地了解 ,
答案 1 :(得分:0)
我认为这是错误的
标量= 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)
x在cos为1或-1时接近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) 这意味着向量是平行的