首页 > 解决方案 > 在执行点积之前对向量进行归一化?

问题描述

我有一个经典练习,要求我检查一个角色是否从背后受到攻击(背刺或射弹)。我知道我可以为此使用点积,我只是想知道我是否必须先对向量进行归一化,或者这无关紧要。

我的理由是,如果矢量坐标是巨大的数字,是否会导致我的点积溢出或下溢。

float dotProd(Vector3& P, Vector3& Q)
{
     return P.x * Q.x + P.y * Q.y + P.z * Q.z;
}

bool sneakAttack(Vector3& proj, Vector3& player)
{
    if(dotProd(proj, player) > 0)
        return true;
    else
        return false;
}

标签: c++math3d

解决方案


规范化可能会使您的代码容易溢出。

假设向量P有长度A并且Q有长度B。为了规范化第一个向量,通常的方法是将每个坐标除以A,这是通过首先计算 A 2获得的,它恰好等于P·P。有问题。如果A >= B,那么P·P >= |P·Q|。因此,如果P·Q溢出,则P·P溢出。在溢出成为您的点积的问题之前,它已经成为规范化的问题。

还有另一个需要注意的危险,这可能是发现您需要处理的值范围的另一个原因。考虑以下情况

  • P.x = 1024,
  • P.y = 0.2,
  • P.z = 1024,

  • Q.x = 1024,
  • Q.y = 0.2, 和
  • Q.z = -1024.

在数学上,这种情况下的点积是P.y * Q.y。但是(^用于表示幂)您的点积计算为(2^20 + 0.04) - 2^202^20和的数量级差异0.04对于 23 位尾数来说太大了。所以他们的总和计算为2^20。减去2^20没有任何迹象表明符号P.y * Q.y是什么。标准化在这里没有帮助,因为它只会将问题转移到 2 的低次方。解决这个问题可能会解决溢出威胁作为副作用。


推荐阅读