你如何规范零矢量

时间:2009-04-06 15:52:32

标签: language-agnostic math vector

假设你有一个函数'normalize',它将一个数字列表(代表一个向量)作为输入,并返回规范化的向量。当向量全为零或其分量之和为零时,结果应该是什么?

10 个答案:

答案 0 :(得分:32)

从数学上讲,零矢量无法归一化。其长度始终为0

对于给定的向量v = (v1, v2, ..., vn),我们有:||v|| = sqrt(v1^2 + v2^2 + ... + vn^2)。让我们记住,规范化的向量是具有||v||=1的那个。

因此对v = 0我们有:||0|| = sqrt(0^2 + 0^2 + ... + 0^2) = 0。你永远无法规范化。

同样重要的是要注意,为确保一致性,您不应返回NaN或任何其他空值。标准化形式的v=0确实是v=0

答案 1 :(得分:12)

甚至比Yuval建议的更糟糕。

在数学上,给定一个向量x,你正在寻找一个新的向量x / || x ||

其中||。||是常态,你可能会认为这是一个欧几里德规范

||。|| = sqrt(dot(v,v))= sqrt(sum_i x_i ** 2)

这些是浮点数,因此仅仅防止除以零是不够的,如果x_i都很小(它们可能下溢并且你失去了幅度),你也会有一个浮点问题。

基本上归结为如果你真的需要能够正确处理小向量,你将不得不做更多的工作。

如果在您的应用程序中使用小向量和零向量,则可以测试向量的大小并执行适当的操作。

(请注意,一旦你开始处理浮点数而不是真实的数字,做平方然后平方根数(或它们的总和)之类的事情在可表示范围的大小两端都是有问题的)

底线:在所有情况下正确地进行数值工作比最初看起来更棘手。

例如,以天真的方式完成此(规范化)操作的潜在问题

  • 所有组件(x_i)太小
  • 任何单个组件太大(高于最大可表示的平方根)将返回无穷大。这会按sqrt。
  • 分组削减可用的幅度
  • 如果大部件与小部件的比例太大,如果不小心,可以有效地丢失小部件方向
  • 等。

答案 2 :(得分:5)

从数学上讲,零矢量无法归一化。这是我们在计算几何中称之为“退化情况”的一个例子,这是一个很大的话题,让几何算法设计者感到非常头疼。 我可以想象以下解决问题的方法。

  1. 你没有对零矢量情况做任何特别的事情。如果矢量类型具有浮点类型坐标,则结果中将得到零或无限坐标(由于除以零)。
  2. 你抛出一个degenerate_case_exception
  3. 您在程序中引入了布尔is_degenerate_case输出参数。
  4. 我个人在代码中到处使用3种方法。它的一个优点是它不会让程序员忘记处理退化的情况。

    注意,由于浮点数的范围有限,即使输入向量不等于零向量,您仍可能在输出向量中得到无限坐标。因此,我不认为1.方法是一个糟糕的设计决策。

    我可以推荐你是为了避免异常抛出解决方案。如果退化情况在其他情况中很少见,那么异常抛出不会减慢程序的速度。但问题是,在大多数情况下,你不可能知道堕落的情况很少见。

答案 3 :(得分:4)

正如已经多次提到的那样,你无法规范零矢量。所以,你的选择是:

  1. 返回零向量
  2. 返回NaN
  3. 返回一个指示向量是否已成功规范化的位,除了成功
  4. 之外的结果
  5. 抛出异常
  6. 选项4不是很好,因为某些语言(例如C)没有异常,并且通常在非常低级的代码中找到规范化向量。抛出异常是相当昂贵的,并且任何可能想要处理零/小向量情况的代码在发生这种情况时将被给予不必要的性能损失。

    选项1的问题是返回值没有单位长度,因此它可以在调用代码中静默引入错误,假定结果向量具有单位长度。

    选项2与选项1有类似的问题,但由于NaN通常比零更明显,因此它可能更容易显现。

    我认为选项3是最好的解决方案,尽管它确实使界面更复杂。而不是说

    vec3 = myVec.normalize();
    

    你现在必须说出像

    这样的话
    vec3 result;
    bool success = myVec.normalize(&result);
    if(success)
        // vector was normalized
    else
        // vector was zero (or small)
    

答案 4 :(得分:3)

非常像0/0。应抛出异常或返回NaN。

答案 5 :(得分:1)

零矢量已经被标准化,在我遇到的矢量范数的任何定义下,所以这是一个案例处理。

对于具有总和为零的分量的向量 - 它取决于您使用的范数的定义。使用普通的旧L2范数(原点和向量之间的欧几里德距离),计算归一化向量的标准公式应该可以正常工作,因为它首先对各个分量进行平方。

答案 6 :(得分:0)

(0,0,0)应该是(0,0,0)标准化加上警告(或例外) 在数学上我猜不定。

答案 7 :(得分:0)

嗯,你必须除以零,这是你不能做的,所以我认为大多数语言会有某种NaN值。

参考文献:

  • XNA
  • Apple(您还必须为矢量选择任意方向)
  • Blender(使用Python)

答案 8 :(得分:0)

给定向量v,对其进行归一化意味着保持其方向并通过将其乘以精心选择的因子来使其成为单位长度。

这对零矢量来说显然是不可能的,因为它实际上没有方向,或者因为它的长度不能通过多个因子多次改变(它总是等于零)。

我建议无论你想使用矢量的任何程序,并且需要对这个矢量进行归一化,对零矢量都没有很好的定义。

答案 9 :(得分:-2)

这一切都取决于你如何定义“规范化”。该术语的一个可能的扩展是说该操作的结果是任何单位长度向量(这里我主要使用(1,0,0))。例如,当您需要标准化以将方向从给定点返回到圆边界时,这很有用。