在C++中创建一个函数,执行Matlab操作[z;z],其中z是矩阵或向量。

3

我想创建一个函数,基本上复制matlab命令:[z;-z],其中z = randn(m,n)返回一个m × n的随机矩阵。我已经能够创建C++中randn函数的函数,如下所示:

MatrixXd generateGaussianNoise(int n, int m){
MatrixXd M(n,m);
normal_distribution<double> nd(0.0, 1.0);
random_device rd;
mt19937 gen(rd());
for(int i = 0; i < n; i++){
    for(int j = 0; j < m; j++){
        M(i,j) = nd(gen);
    }
}
return M;

现在我需要创建 [z;-z] 函数。例如,假设 z = randn(2,2),那么输出将是:

   -2.2588    0.3188
    0.8622   -1.3077

现在,当我写 [z;-z] 时,我们会得到:
   -2.2588    0.3188
    0.8622   -1.3077
    2.2588   -0.3188
   -0.8622    1.3077

我想创建一个函数,该函数接受矩阵或向量z,将这些条目存储在另一个矩阵或向量中,然后创建一个新的矩阵或向量,使其大小加倍以将相关条目放置在正确的(i,j)位置。
我不确定这是否是我应该采取的方法。非常感谢您的任何意见或建议。顺便说一下,我在C++方面还有点新手。
3个回答

2

首先,您应该使用矩阵中的rowscols来初始化输出矩阵的正确大小。然后,您可以使用逗号初始化语法通过将一个矩阵与相同矩阵的负值垂直连接来填充此矩阵。

MatrixXd A(n, m);

normal_distribution<double> nd(0.0, 1.0);
random_device rd;
mt19937 gen(rd());

// Fill up the matrix
for(int i = 0; i < n; i++){
    for(int j = 0; j < m; j++){
        A(i, j) = nd(gen);
    }
}

// Vertically concatenate the matrix with the negative version
MatrixXd B(A.rows() * 2, A.cols());
B << A, -A;

return B;

那里的代码似乎和我的答案一样。它直接计算输出,而不是连接,所以它不适合你的答案。当将其连接到自身时,您应该使用原始帖子中的代码。 - anatolyg
@anatolyg 哎呀,忘记删掉那一行了。我只是借用它来填充数据作为一个完整的例子。现在已经更新了。 - Suever
@mweiss1 嗯,再看一下你的例子,它是 4 x 2。在 MATLAB 中,语法 [z; z] 也会给你一个 4 x 2。 - Suever
@mweiss1 如果你按照我的代码中最后三行的操作,那么它将创建一个新的矩阵,该矩阵是z-z值的简单连接,并且不会改变z - Suever
由于某种原因,我无法发布新问题,因为它说我需要每90分钟发布一个问题,而已经过去了。我的问题是如何在Eigen库中使用模运算符,我尝试了fmod()和%但似乎都不起作用...有什么想法吗? - user7465838
显示剩余5条评论

0

我想这应该足够了吧?

MatrixXd generateGaussianNoise(int n, int m){
MatrixXd M(2*n,m);
normal_distribution<double> nd(0.0, 1.0);
random_device rd;
mt19937 gen(rd());
for(int i = 0; i < n; i++){
    for(int j = 0; j < m; j++){
        double r = nd(gen);
        M(i,j) = r;
        M(n+i,j) = -r;
    }
}
return M;

0

你可以使用填充m行n列矩阵的代码,并添加另一段代码将该矩阵“加倍”为2m行n列矩阵。

然而,在C++中,通常应立即分配正确的维度,并且只需执行一次。

也就是说:

MatrixXd M(2 * n, m);

(顺便提一下,请决定您的矩阵是m×n还是n×m;这非常重要,以防混淆)
然后,在填充矩阵时,每次迭代写入两个元素:
for(int i = 0; i < n; i++){
    for(int j = 0; j < m; j++){
        double element = nd(gen);
        M(i, j) = element;
        M(i + n, j) = -element;
    }
}

如果你要处理大矩阵,你应该记住元素是按列主序存储在内存中的(除非你决定覆盖这个选择)。Matlab也使用这种顺序。因此,为了更好地处理大矩阵,你应该填充它们,使每一列都在另一列之前填充。所以你应该交换循环的嵌套顺序:

for(int j = 0; j < m; j++){
    for(int i = 0; i < n; i++){
        double element = nd(gen);
        M(i, j) = element;
        M(i + n, j) = -element;
    }
}

在这里,连续的两次迭代将写入相邻的内存地址,这很可能会有更好的性能。


我可能没有理解你想表达的意思,因为你将以“j”开头而不是“i”的顺序进行了切换。你是说对于生成正态分布随机数的函数,如果我要使用大矩阵,那么第一个for循环中需要以“j”开始吗?抱歉让你感到困惑。 - user7465838
此外,为什么列会加倍而行不会呢?在我的例子中,一个2乘2的矩阵变成了一个4乘4的矩阵。 - user7465838

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接