行列の初期化についての備忘録

##行列（2次元配列）

今回はc言語で行列の初期化を行おうとした時に生じたエラーとその解決策について記す。
今回の記事は備忘録がメインです。
**code_ver1,ver2のカウンタ関数の使い方に配列のサイズの認識不足による間違いがあります。**

入力したい行列は以下のようなものである。

```c
matrix = {{1, 1/2, 1/3, 1/4, 1/5, 1/6},
          {1/2, 1/3, 1/4, 1/5, 1/6, 1/7},
          {1/3, 1/4, 1/5, 1/6, 1/7, 1/8},
          {1/4, 1/5, 1/6, 1/7, 1/8, 1/9},
          {1/5, 1/6, 1/7, 1/8, 1/9, 1/10},          
          {1/6, 1/7, 1/8, 1/9, 1/10, 1/11}}
```
~~普通に上記のような行列が欲しいが実際にこのように行列を初期化する時に要素中に演算子を含ませることはできないので、分数表示でなく、少数表示のmatrixを求めるコードを書いて見た。~~
**配列の要素に演算子を含めることはできました。次のコードでも問題なくコンパイルすることができました。**

```c
float matrix[6][6] =
        {{1, 1/2, 1/3, 1/4, 1/5, 1/6},
        {1/2, 1/3, 1/4, 1/5, 1/6, 1/7},
        {1/3, 1/4, 1/5, 1/6, 1/7, 1/8},
        {1/4, 1/5, 1/6, 1/7, 1/8, 1/9},
        {1/5, 1/6, 1/7, 1/8, 1/9, 1/10},
        {1/6, 1/7, 1/8, 1/9, 1/10, 1/11}};
```



**for文の使い方の例として以下を残しておきます**
まず、最初に以下のようなコードを実行してみた。

```c
//code_ver1
//カウンタ関数iの範囲がi=0からi<7になっているが正しくはi<6までで十分
int main(void)
{
    int matrix[6][6];
    for(int i=0; i<7; i++)
    matrix[0][i] = 1 / (i+1);
    
    for(int i=0; i<7; i++)
    matrix[1][j] = 1 / (i+2);
    
    for(int i=0; i<7; i++)
    matrix[2][i] = 1 / (i+3);
    
    for(int i=0; i<7; i++)
    matrix[3][i] = 1 / (i+4);
    
    for(int i=0; i<7; i++)
    matrix[4][i] = 1 / (i+5);
    
    for(int i=0; i<7; i++)
    matrix[5][i] = 1 / (i+6);
    
    for(int i=0; i<6; i++)
    {
        for(int j=0; j<6; j++)
        printf("i=%d, j=%d, matrix[i][j]=%d\n", i,j,matrix[i][j]);
    }    
}
```


実行結果としては以下のような結果になった。
<details><summary>実行結果（result_ver1）</summary><div>

```c
i=0, j=0, matrix[i][j]=1
i=0, j=1, matrix[i][j]=0
i=0, j=2, matrix[i][j]=0
i=0, j=3, matrix[i][j]=0
i=0, j=4, matrix[i][j]=0
i=0, j=5, matrix[i][j]=0
i=1, j=0, matrix[i][j]=0
i=1, j=1, matrix[i][j]=0
i=1, j=2, matrix[i][j]=0
i=1, j=3, matrix[i][j]=0
i=1, j=4, matrix[i][j]=0
i=1, j=5, matrix[i][j]=0
i=2, j=0, matrix[i][j]=0
i=2, j=1, matrix[i][j]=0
i=2, j=2, matrix[i][j]=0
i=2, j=3, matrix[i][j]=0
i=2, j=4, matrix[i][j]=0
i=2, j=5, matrix[i][j]=0
i=3, j=0, matrix[i][j]=0
i=3, j=1, matrix[i][j]=0
i=3, j=2, matrix[i][j]=0
i=3, j=3, matrix[i][j]=0
i=3, j=4, matrix[i][j]=0
i=3, j=5, matrix[i][j]=0
i=4, j=0, matrix[i][j]=0
i=4, j=1, matrix[i][j]=0
i=4, j=2, matrix[i][j]=0
i=4, j=3, matrix[i][j]=0
i=4, j=4, matrix[i][j]=0
i=4, j=5, matrix[i][j]=0
i=5, j=0, matrix[i][j]=0
i=5, j=1, matrix[i][j]=0
i=5, j=2, matrix[i][j]=0
i=5, j=3, matrix[i][j]=0
i=5, j=4, matrix[i][j]=0
i=5, j=5, matrix[i][j]=0
Program ended with exit code: 0
```
</div></details>

まずcode_ver1はfor文をもう一つ使えばもっと短く書けるのだが、確認のためにfor文を各行に一回ずつ使用して描いてみた。

反省点
・計算結果はfloat型になるのにint型でmatrixを定義していた。
・割り算を行う時1も(i+1)もint型なので計算結果もint型で表示される。

この２点について留意してデバックすると以下のようなコードになる。
ここでは前回まとめたキャスト（明示的型変換）を行うことで、商がfloat型で表示されるようにしている。
前回の記事のurlを一応載せておく。
[データ型の考慮](https://qiita.com/Kou27/items/e33510e5cc5d4dcd1ea0)

```c
//code_ver2
//カウンタ関数iの範囲がi=0からi<7になっているが正しくはi<6までで十分
int main(void)
{
    float matrix[6][6];
    for(int i=0; i<7; i++)
    matrix[0][i] = (float)1 / (i+1);
    
    for(int i=0; i<7; i++)
    matrix[1][i] = (float)1 / (i+2);
    
    for(int i=0; i<7; i++)
    matrix[2][i] = (float)1 / (i+3);
    
    for(int i=0; i<7; i++)
    matrix[3][i] = (float)1 / (i+4);
    
    for(int i=0; i<7; i++)
    matrix[4][i] = (float)1 / (i+5);
    
    for(int i=0; i<7; i++)
    matrix[5][i] = (float)1 / (i+6);
    
    for(int i=0; i<6; i++)
    {
        for(int j=0; j<6; j++)
        printf("i=%d, j=%d, matrix[i][j]=%f\n", i,j,matrix[i][j]);
    }
    
}

```

すると、希望の行列が少数表示で得られた。
<details><summary>実行結果（result_ver2）</summary><div>

```c
//result_ver2
i=0, j=0, matrix[i][j]=1.000000
i=0, j=1, matrix[i][j]=0.500000
i=0, j=2, matrix[i][j]=0.333333
i=0, j=3, matrix[i][j]=0.250000
i=0, j=4, matrix[i][j]=0.200000
i=0, j=5, matrix[i][j]=0.166667
i=1, j=0, matrix[i][j]=0.500000
i=1, j=1, matrix[i][j]=0.333333
i=1, j=2, matrix[i][j]=0.250000
i=1, j=3, matrix[i][j]=0.200000
i=1, j=4, matrix[i][j]=0.166667
i=1, j=5, matrix[i][j]=0.142857
i=2, j=0, matrix[i][j]=0.333333
i=2, j=1, matrix[i][j]=0.250000
i=2, j=2, matrix[i][j]=0.200000
i=2, j=3, matrix[i][j]=0.166667
i=2, j=4, matrix[i][j]=0.142857
i=2, j=5, matrix[i][j]=0.125000
i=3, j=0, matrix[i][j]=0.250000
i=3, j=1, matrix[i][j]=0.200000
i=3, j=2, matrix[i][j]=0.166667
i=3, j=3, matrix[i][j]=0.142857
i=3, j=4, matrix[i][j]=0.125000
i=3, j=5, matrix[i][j]=0.111111
i=4, j=0, matrix[i][j]=0.200000
i=4, j=1, matrix[i][j]=0.166667
i=4, j=2, matrix[i][j]=0.142857
i=4, j=3, matrix[i][j]=0.125000
i=4, j=4, matrix[i][j]=0.111111
i=4, j=5, matrix[i][j]=0.100000
i=5, j=0, matrix[i][j]=0.166667
i=5, j=1, matrix[i][j]=0.142857
i=5, j=2, matrix[i][j]=0.125000
i=5, j=3, matrix[i][j]=0.111111
i=5, j=4, matrix[i][j]=0.100000
i=5, j=5, matrix[i][j]=0.090909
Program ended with exit code: 0
```
</div></details>


**（追記）**
上のコードver1, ver2ではiの範囲を0から6に設定しているが、行列のサイズは6でc言語の配列は0スタートなので正しくはiの範囲は0から5(i=0; i<6)とするべきでした。
出力する時にはなぜか範囲の設定が正しいので目に見える結果では正しいかのように見える。

ここからは本質ではないが、練習のためにfor文を使ってさらに短く書いてみた。
また出力もこのままだと見にくいので、6行6列の行列として見やすく表示した。

```c
//code_ver3
int main (void)
{
    float matrix[6][6];
    
    for(int i=0; i<6; i++)
    for(int j=0; j<6; j++)
    {
        matrix[i][j] = (float)1 / (j+i+1);
        
    }
    printf("matrix[6][6] = {");
    for(int i=0; i<6; i++)
    {
        printf("{");
        for(int j=0; j<6; j++)
        {
            printf("%f,", matrix[i][j]);
        }
        printf("}");
        printf("\n");
    }
    printf("}");
}
```

```c
//result_ver3
matrix[6][6] = {{1.000000,0.500000,0.333333,0.250000,0.200000,0.166667,}
{0.500000,0.333333,0.250000,0.200000,0.166667,0.142857,}
{0.333333,0.250000,0.200000,0.166667,0.142857,0.125000,}
{0.250000,0.200000,0.166667,0.142857,0.125000,0.111111,}
{0.200000,0.166667,0.142857,0.125000,0.111111,0.100000,}
{0.166667,0.142857,0.125000,0.111111,0.100000,0.090909,}
}Program ended with exit code: 0
```