稀疏矩阵中的元素数量被视为非零元素的数量,而非维度之积。因此,
SparseMatrix sm; ... int nnz = sm.nelem ();
返回的是非零元素的数量(与解释器函数 nnz 的行为一致)。如果用户确实需要矩阵中的元素总数(包括零元素),则应使用 numel 而非 nelem。需要注意的是,对于非常大的矩阵,当两个维度的乘积超出无符号整型所能表示的范围时,numel 可能会溢出。例如,speye (1e6) 会创建一个一百万行和一百万列的矩阵,但其中只有一百万个非零元素。在这种情况下,行数与列数的乘积超过无符号 32 位整型所能表示最大值的二百倍以上。因此,除非确定不会发生溢出,否则应避免使用 numel。
在使用功能几乎相同的 elem 方法或 () 运算符时,也需要格外小心。原因在于,如果稀疏对象是非 const 的,Octave 会将对稀疏矩阵中零元素的访问视为创建该元素以便后续填充的请求。因此,如下代码
SparseMatrix sm;
...
for (int j = 0; j < nc; j++)
for (int i = 0; i < nr; i++)
std::cerr << " (" << i << "," << j << "): " << sm(i,j) << "\n";
是将稀疏矩阵转化为稠密矩阵的绝佳方式——而且速度极慢,因为它会为矩阵中的每个零元素重新分配稀疏对象。
防止上述情况发生的一个简单方法是创建一个稀疏矩阵的临时常量版本。请注意,这只会复制稀疏矩阵的容器,而实际的底层数据将在两个版本之间共享;因此该操作的开销并不大。将上述示例改写以避免稀疏到稠密转换后的代码如下:
SparseMatrix sm;
...
const SparseMatrix tmp (sm);
for (int j = 0; j < nc; j++)
for (int i = 0; i < nr; i++)
std::cerr << " (" << i << "," << j << "): " << tmp(i,j) << "\n";
最后,由于稀疏类型不是由连续的内存块表示的,因此 Array<T> 的 rwdata 方法不可用。取而代之的是三种不同的方法:ridx、cidx 和 data,它们用于访问 Octave 稀疏矩阵所存储的原始压缩列格式。这些方法的使用方式与 elem 类似,可以访问或填充矩阵。然而,用户必须正确遵循稀疏矩阵的压缩列格式规范,否则矩阵将损坏。
版权所有 © 2024-2026 Octave中文网
ICP备案/许可证号:黑ICP备2024030411号-2