Как инициализировать двойную матрицу с элементом NaN? - PullRequest
0 голосов
/ 02 июня 2018

в моем коде у меня есть двойная матрица, подобная этой:

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 голосов
/ 03 июня 2018

Во-первых, настоятельно избегайте самостоятельного использования сырых указателей в 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);
}

Этот код все еще не то, что вы хотите.Обычно не рекомендуется создавать свою матрицу NxN, используя N вызовов new или n конструкций вектора.Сделайте одно распределение NxN double, а затем либо оберните его в класс MyMatrix, который поддерживает 2-параметрический оператор квадратной скобки, т. Е.

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 или другом значении (в конструкторе) и без использования двух указателей каждый раз, когда выполучить доступ к нему.

0 голосов
/ 03 июня 2018

Если вы хотите использовать массивы статического размера, вам лучше использовать 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 ++ надС конструкции.Они более безопасны по типу и IMHO почти всегда удобнее в использовании, например, передача std::array объектов в качестве параметров не отличается от любых других объектов.Если вы пришли из C-фона и у вас нет опыта работы с C ++, я бы порекомендовал прочитать текст учебника, в котором сначала не вводится C, например The Tour of C ++,

0 голосов
/ 02 июня 2018

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("")));
...