2014-02-20 103 views
0

我正在做一些非常基本的線性代數,我可能完全在這裏忽略了這一點。C++ - 矩陣減法

比方說,我有以下矩陣:

v1 = [5, 8] 
v2 = [3, 4] 
v3 = [4, 4] 
v4 = [2, 1] 

預期輸出:

M1 = [5 - 3, 8 - 4] = [2, 4] 
M2 = [4 - 2, 4 - 1] = [2, 3] 

實際輸出:

0 0 
0 0 
2 4 
-1 0 
2 3 

下面是代碼:

std::vector<double> calculate(std::vector<double> values, std::vector<double> values2) 
{ 
    std::vector<double> vel(2, 0); 

    for(unsigned i=0; (i < values.size()); i++) 
    { 
     vel[i] = values[i] - values2[i]; 
    } 

    return vel; 
} 



    std::vector<std::vector<double> > values = { {5,8}, {3, 4}, {4, 4}, {2, 1}}; 

    std::vector<std::vector<double> > v; 

    v.resize(2); 

    for(unsigned i=0; (i < values.size()-1); i++) 
    { 
     v[i].resize(2); 
     v.push_back(calculate(values[i], values[i + 1])); 
     //v[i] = calculate(values[i], values[i + 1]); 
    } 

    for(unsigned i=0; (i < v.size()); i++) 
    { 
     for(unsigned j=0; (j < v[i].size()); j++) 
     { 
      std::cout << v[i][j] << " "; 
     } 
     std::cout << std::endl; 
    } 

問題在於,以下應該重複4次,計算4個矩陣,最終的結果2D矢量應該只包含2個值。

我可能錯過了一些愚蠢的東西。

+0

附加後,我覺得邏輯就變得如果您爲每個矩陣分別考慮兩個矢量,則更容易。對這兩個矩陣採用單個向量使代碼有點不可讀。 – Mahesh

+3

您應該真的使用像[armadillo](http://arma.sourceforge.net/)這樣的C++線性代數庫。儘管命名,「std :: vector」對於線性代數來說有一個糟糕的界面。你遇到的具體問題就是你正在弄亂元素的大小和位置。 –

+1

或者只是標準的valarray,你試圖實現的任務很容易用valarray實現,比如:v1-v2。結束 – 4pie0

回答

2
v.resize(2); // now it contains `{{} {}}`. 
for(unsigned i=0; (i < values.size()-1); i++) //for each input except the last (3 iterations) 
        //starting with {5,8} and {3,4} 
    v[i].resize(2); //resize one of the vectors already in v to 2 
        //now v contains {{0,0}, {} 
    v.push_back(calculate(values[i], values[i + 1])); //push back the calculations 
        //now v contains {{0,0}, {}, {2,4}} 
for(............. (i < values.size()-1); i++) 
        //next the middle pair of inputs {3,4} and {4,4} 
    v[i].resize(2); //resize one of the vectors already in v to 2 
        //now v contains {{0,0}, {0,0}, {2,4}} 
    v.push_back(calculate(values[i], values[i + 1])); //push back the calculations 
        //now v contains {{0,0}, {0,0}, {2,4}, {-1,0}} 
for(............. (i < values.size()-1); i++) 
        //finally the last pair of inputs {4,4} and {2,1} 
    v[i].resize(2); //resize the {2,4} to 2, but it was already two 
        //now v contains {{0,0}, {0,0}, {2,4}, {-1,0}} 
    v.push_back(calculate(values[i], values[i + 1])); //push back the calculations 
        //now v contains {{0,0}, {0,0}, {2,4}, {-1,0}, {2,3}} 
for(............. (i < values.size()-1); ....) //done iterating 

你有調試器嗎?學習如何逐步完成這樣的代碼,讓別人展示你或者找到教程是非常重要的。在調試器中瀏覽這段代碼會讓你知道發生了什麼。

幸運的是,代碼是很容易解決:

std::vector<std::vector<double> > v; 

for(unsigned i=0; i<values.size()-1; i+=2) //NOTE: i+=2!!! 
{ 
    v.push_back(calculate(values[i], values[i + 1])); 
} 

證明:http://coliru.stacked-crooked.com/a/827a0183f1e7c582

+0

嘿,謝謝你。但是,它不起作用。我只是得到'2 4',而我需要另外一個有兩個以上值的矩陣。 – Phorce

+0

你必須改變別的東西。在這篇文章中的代碼工作正常,我剛剛測試:http://coliru.stacked-crooked.com/a/827a0183f1e7c582 –

1
for(unsigned i=0; (i < values.size()-1); i++) 
{ 
    v[i].resize(2); 
    v.push_back(calculate(values[i], values[i + 1])); 
    //v[i] = calculate(values[i], values[i + 1]); 
} 

這個循環運行在的values兩個元素,所以,計數器需要通過2增加每迭代。否則你會減去v1-v2,v2-v3,v3-v4等等。另外,在push_back之前不需要確定向量大小(並且它實際上是危險的,因爲在元素被推回之前索引可能是越界的)。

for(unsigned i=0; (i < values.size()-1); i+=2) 
{ 
    //v[i].resize(2); 
    v.push_back(calculate(values[i], values[i + 1])); 
    //v[i] = calculate(values[i], values[i + 1]); 
} 

正如所指出的其他v.resize(2);不應該有可能是因爲它只是增加了兩個空的元素開始,你不想要的。

+0

你好,不,可悲的是,這並沒有工作..只是打印'0 0' – Phorce

+0

@ user1326876修正了一些事情。希望它現在可以工作。 – Nabla

+0

非常感謝:) – Phorce

1
v.resize(2); 

我不知道是你所期待以上的事,但這個(加上下面的代碼)是對前兩行輸出負責的。

for(unsigned i=0; (i < values.size()-1); i++) 
{ 
    v[i].resize(2); 

我不知道是你所期待以上的事,但這個(加上上面的代碼)就是負責輸出這些前兩行。

以下是發生了什麼:您的第一個調整大小(循環外調整大小)使用兩個空矢量填充v。前兩個循環通過循環填充爲v[0]v[1]作爲兩個元素均爲零的雙元向量。

v.push_back(calculate(values[i], values[i + 1])); 

這將最終增加三個元件v,一個是{5,8} - {3,4} = {2,4},在下次{3,4-} - {4,4- } = { - 1,0},最後是{4,4} - {2,1} = {2,3}。所以,你的輸出應該是

0 0 
0 0 
2 4 
-1 0 
2 3 

要擺脫那些前兩行,只需將兩個電話上刪除對resize。要擺脫倒數第二行(即-1 0位於兩個所需的輸出行之間),請將循環增量從一個(i++)更改爲兩個(i += 2)。

0

此輸出

0 0 
    0 0 
    2 4 
    -1 0 
    2 3 

可以非常簡單地解釋

起初使用方法調整

v.resize(2); 

您在矢量V增加了兩個空的std ::向量。

然後在迴路中

for(unsigned i=0; (i < values.size()-1); i++) 
{ 
    v[i].resize(2); 
    v.push_back(calculate(values[i], values[i + 1])); 
    //v[i] = calculate(values[i], values[i + 1]); 
} 

您調整了其中的每一個。所以,現在v [0]和v [1]是

0 0 
0 0 

然後你得到的

values[0] - values[1] 
values[1] - values[2] 
values[2] - values[3] 

減法是矢量V與

2 4 
    -1 0 
    2 3