21.5 Различия в обработке нулевых элементов
Представление диагональных и перестановочных матриц в виде самостоятельных специальных объектов и, как следствие, использование более эффективных алгоритмов для некоторых операций приводят, в частности, к небольшим различиям в обработке нулей. Содержание этого раздела также применимо к разреженным матрицам, рассматриваемым в следующей главе. (см. Разреженные матрицы)
Стандарт IEEE для арифметики с плавающей точкой определяет результат выражений 0*Inf и 0*NaN как NaN. Такой компромисс широко признаётся удачным. Однако в численных программах, работающих со структурированными и разреженными матрицами (включая Octave), почти всегда различают «численный ноль» и «подразумеваемый ноль». «Численный ноль» — это нулевое значение в месте, где может находиться любое значение с плавающей точкой. Обычно он где-либо хранится в памяти как явное значение. «Подразумеваемый ноль», напротив, — это нулевой элемент матрицы, обусловленный структурой матрицы (диагональной, треугольной) или шаблоном разреженности; его значение обычно нигде явно не хранится, а подразумевается базовой структурой данных.
Основное различие заключается в том, что при умножении подразумеваемого нуля на любое число или при делении на любое ненулевое число результатом всегда будет ноль, даже если, например, он умножается на Inf или делится на NaN. Такое поведение объясняется тем, что базовый алгоритм фактически нигде не выполняет численное умножение; результат просто считается равным нулю. Иными словами, можно сказать, что часть вычислений с подразумеваемыми нулями выполняется символически, а не численно.
Такое поведение не только упрощает наиболее прямолинейную и эффективную реализацию алгоритмов, но и сохраняет некоторые полезные инварианты, например:
- произведение скаляра на диагональную матрицу является диагональной матрицей
- деление разреженной матрицы на скаляр сохраняет шаблон разреженности
- произведение матрицы перестановок на матрицу эквивалентно перестановке строк
все эти естественные математические истины перестали бы выполняться, если бы подразумеваемые нули обрабатывались как численные.
Обратите внимание, что MATLAB не всегда строго следует этому принципу и в некоторых случаях преобразует подразумеваемые нули в численные, а в других — нет. На сегодняшний день нет намерений воспроизводить такое поведение в Octave.
Примеры последствий различия между подразумеваемыми и численными нулями:
Inf * eye (3)
⇒
Inf 0 0
0 Inf 0
0 0 Inf
Inf * speye (3)
⇒
Compressed Column Sparse (rows = 3, cols = 3, nnz = 3 [33%])
(1, 1) -> Inf
(2, 2) -> Inf
(3, 3) -> Inf
Inf * full (eye (3))
⇒
Inf NaN NaN
NaN Inf NaN
NaN NaN Inf 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
© 1996–2026 The Octave Project Developers
Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.
Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions.
https://docs.octave.org/v9.4.0/Zeros-Treatment.html