如何使用NaN元素初始化双矩阵?

时间:2018-06-02 18:23:28

标签: c++ c++11 nan

在我的代码中,我有一个像这样的双矩阵:

double * * matrix=new double * [10];
for(int i=0;i<10;i++) 
    matrix[i]=new double[10];

我希望在初始化时,在此矩阵的每个单元格中都有 NaN值,是否可以自动执行或唯一的解决方案是:

for(int i=0;i<10;i++)
    for(int j=0;j<10;j++)
        matrix[i][j]=nan("");

是否有可能推断出当矩阵将进行结构化时,它不会使用双重插入的默认构造函数,对于每个矩阵[i] [j],0.0值但插入nan(“”)?

3 个答案:

答案 0 :(得分:1)

double没有默认构造函数,即默认情况下double值未初始化。

为避免显式实现循环,您可以使用std::vector

#include <vector>
...
std::vector<std::vector<double>> matrix(10, std::vector<double>(10, nan("")));

或:

#include <vector>
using namespace std;
...
vector<vector<double>> matrix(10, vector<double>(10, nan("")));

答案 1 :(得分:1)

首先,强烈避免自己在C ++中使用原始指针 - 这几乎总是一个坏主意。如果没有适合的容器类,请使用std::unique_ptr。所以你的代码变成了:

auto matrix = std::make_unique<double* []>(10);
for(int i=0;i<10;i++)  {
    matrix.get()[i]= std::make_unique<double []>(10);
}

此代码仍然不是您想要的。使用N个new调用或n个向量构造来创建NxN矩阵通常不是一个好主意。单独分配NxN双精度数,然后将其包装在支持2参数方括号运算符的类MyMatrix中,即

template <typename T>
class MyMatrix { 
   // etc. etc
   double const T& operator[](size_type i, size_type j) const { return data_[i*n + j]; }
   double T& operator[](size_type i, size_type j) { return data_[i*n + j]; }
}

或(不推荐)让指针指向单一分配区域:

size_t n = 10;
auto matrix_data = std::make_unique<double []>(n * n);
auto matrix = std::make_unique<double* []>(n);
for(int i=0;i<10;i++)  {
    matrix.get()[i] = matrix_data.get() + i * n;
}

在每种情况下,您可以稍后使用std::fill将所有矩阵值设置为NaN,在任何循环之外。

上面的最后一个例子也可以转换为使用向量(如果你不使用自己的类,这可能比原始指针更好):

size_t n = 10;
auto matrix_data = std::vector<double>(n * n);
auto matrix = std::vector<double*>(n);
for(auto& row : matrix) {
    auto row_index = std::dist(row, matrix.begin());
    row = &matrix_data[row_index * n];
}

同样,我不建议这样做 - 它仍然是一种类似于C的方式来启用my_matrix[i][j]语法,而使用包装类可以让你my_matrix[i,j]而不需要额外的存储,初始化为NaN或其他值(在构造函数中),每次访问时都不会跟随两个指针。

答案 2 :(得分:0)

如果您想使用静态大小的数组,最好使用std::array。为了更方便地使用多维std::array,您可以使用模板别名

template <class T, size_t ROW, size_t COL>
using Matrix = std::array<std::array<T, COL>, ROW>;

您可以使用std::array::fill设置矩阵中的值,例如

Matrix<double, 3, 4> m = {};
m.fill(42.0);

您还可以创建一个使用默认值初始化的编译时常量矩阵对象,以便在运行时使用简单的constexpr函数跳过初始化。

template<typename T, size_t R, size_t C>
constexpr auto makeArray(T&& x) {
    Matrix<T,R,C> m = {};
    for(size_t i=0; i != R; ++i) {
        for(size_t j=0; j != C; ++j) {
            m[i][j] = std::forward<T>(x);
        }
    }
    return m;
}

auto constexpr m = makeArray<double, 3,4>(23.42);

我将重复给出比C结构更喜欢C ++结构的建议。它们更安全,IMHO几乎总是更方便使用,例如传递std::array个对象作为参数与任何其他对象没有区别。如果您来自C背景并且没有其他C ++经验,我建议您阅读一些不首先介绍C的教程文本,例如: The Tour of C++,