21.5 零元素处理的差异

将对角矩阵和置换矩阵本身设置为特殊的矩阵对象,并因此对某些运算使用更智能的算法,这作为附带效果会导致在零元素处理上产生微小差异。本节的内容也适用于稀疏矩阵,将在下一章中讨论(请参见稀疏矩阵)。

IEEE 754 浮点标准定义了表达式 0*Inf0*NaN 的结果为 NaN。这被广泛认为是一个良好的折衷方案,Octave 始终力求遵循这一标准。然而,某些专为结构化和稀疏矩阵最大化效率而设计的算法可能不符合 IEEE 754 浮点标准中关于零元素操作的规定——这些操作本应得到 NaN,例如 0*Inf0/00*NaN

处理结构化和稀疏矩阵的数值软件(包括 Octave)几乎总是区分"数值零"和"假定为零"。一个"数值零"是在可能发生任何浮点值的位置出现的零值,通常会作为显式值存储在内存中。相比之下,一个"假定为零"是由矩阵结构(对角、三角)或稀疏模式隐含的零矩阵元素;它的值通常不会在任何地方显式存储,而是由底层数据结构隐含。

主要的区别在于,一个假定零乘以或除以任何数都总是产生零,即使乘以 Inf 或除以 NaN 也是如此。这种行为的原因是底层算法实际上并未在任何位置执行数值乘法;结果只是被假定为零。

Octave 通过将底层算法分支到专门的实现来处理实际影响假定零的操作,从而缓解了这一问题。这主要是在计算效率与遵循浮点标准(即将假定零视为数值零)之间进行权衡。除了计算速度的差异之外,这种行为还会影响稀疏模式,在处理非常大的稀疏矩阵时应考虑到这一点,否则可能导致内存溢出错误。

在稀疏矩阵中将假定零视为数值零的运算示例:

speye (3)
⇒ 
Compressed Column Sparse (rows = 3, cols = 3, nnz = 3 [33%])
  (1, 1) -> 1
  (2, 2) -> 1
  (3, 3) -> 1
Inf * speye (3)
⇒ 
Compressed Column Sparse (rows = 3, cols = 3, nnz = 9 [100%])
  (1, 1) -> Inf
  (2, 1) -> NaN
  (3, 1) -> NaN
  (1, 2) -> NaN
  (2, 2) -> Inf
  (3, 2) -> NaN
  (1, 3) -> NaN
  (2, 3) -> NaN
  (3, 3) -> Inf
Inf * full (eye (3))
⇒ 
   Inf   NaN   NaN
   NaN   Inf   NaN
   NaN   NaN   Inf
speye (3) / 0
⇒ 
Compressed Column Sparse (rows = 3, cols = 3, nnz = 9 [100%])
  (1, 1) -> Inf
  (2, 1) -> NaN
  (3, 1) -> NaN
  (1, 2) -> NaN
  (2, 2) -> Inf
  (3, 2) -> NaN
  (1, 3) -> NaN
  (2, 3) -> NaN
  (3, 3) -> Inf
full (eye (3)) / 0
⇒ 
   Inf   NaN   NaN
   NaN   Inf   NaN
   NaN   NaN   Inf

虽然在稀疏矩阵中,只有稀疏模式可能会受到某些操作的影响,但在处理对角矩阵时,这些操作还可能影响返回的类型。适用以下规则:

例如:

3 * eye (3)
⇒ 
Diagonal Matrix
   3   0   0
   0   3   0
   0   0   3
Inf * eye (3)
⇒ 
      Inf      NaN      NaN
      NaN      Inf      NaN
      NaN      NaN      Inf
eye (3) / 0
⇒ 
      Inf      NaN      NaN
      NaN      Inf      NaN
      NaN      NaN      Inf
eye (3) / NaN
⇒ 
      NaN      NaN      NaN
      NaN      NaN      NaN
      NaN      NaN      NaN
eye (3) / Inf
⇒ 
Diagonal Matrix
   0   0   0
   0   0   0
   0   0   0
eye (3) / 2
⇒ 
Diagonal Matrix
   0.5000        0        0
        0   0.5000        0
        0        0   0.5000

请注意,Octave(以及 MATLAB)并不严格遵循 IEEE 754 浮点标准,在某些情况下(如下面的示例所示),底层算法在假定零下运作而不将其视为数值零。自 Octave 11 起,目标在于使 Octave 完全符合 IEEE 754 标准,从而对稠密矩阵、稀疏矩阵或任何其他特殊矩阵类型的运算产生一致的结果。因此,以下示例中的输出预计会在未来的 Octave 版本中发生变化。

假定零与数值零的效果示例:

diag (1:3) * [NaN; 1; 1]
⇒ 
   NaN
     2
     3
sparse (1:3,1:3,1:3) * [NaN; 1; 1]
⇒ 
   NaN
     2
     3
[1,0,0;0,2,0;0,0,3] * [NaN; 1; 1]
⇒ 
   NaN
   NaN
   NaN

版权所有 © 2024-2026 Octave中文网

ICP备案/许可证号:黑ICP备2024030411号-4