hamua
@hamua

Are you sure you want to delete the question?

If your question is resolved, you may close it.

Leaving a resolved question undeleted may help others!

We hope you find it useful!

ポインタ配列への値の代入方法に関する質問

解決したいこと

2つの関数の違いを知りたいです。
ソースコードはinputにフィルタを掛けて値をoutputに代入する関数です。
2つのプログラムはouput[i]の代入の仕方が違うのですが、
以下のように2回呼び出すと、1)一時変数sumを利用。は正しい配列の値になり、
2)直接outputに累積加算。は間違った値になります。

新:想定していた呼び出し。

 ApplyFilter(input, output1, filter, windowSize, dataSize);
 ApplyFilter(input, output2, filter, windowSize, dataSize);  

旧:ミス。

 ApplyFilter(input, output, filter, windowSize, dataSize);
 ApplyFilter(input, output, filter, windowSize, dataSize);  

ChatGPTには「output配列に以前の値が残っている」と返ってきたのですが、
新しく参照しているなぜ以前の値が残るか理解できてないです。
今回、ポインタを配列と同じように扱ってはなぜ駄目か教えて頂きたいです。

該当するソースコード

1)一時変数sumを利用。

void ApplyFilter(float *input, float *output, float *filter, int windowSize, int dataSize) {
  for (int i = 0; i < dataSize; i++) {
    float sum = 0;
    for (int j = 0; j < windowSize; j++) {
        int dataIndex = i + j - HalfPeriod;
        // border type is used "reflect": (d c b a | a b c d | d c b a) 
        if (dataIndex < 0) {
            dataIndex = -dataIndex - 1;
        } else if (dataIndex >= dataSize) {
            dataIndex = dataSize - (2* (dataIndex - dataSize) + 1);
        }

        sum += input[dataIndex] * filter[j];
    }
    output[i] = sum;
  }
}

2)直接outputに累積加算。

void ApplyFilter(float *input, float *output, float *filter, int windowSize, int dataSize) {
  for (int i = 0; i < dataSize; i++) {
    for (int j = 0; j < windowSize; j++) {
        int dataIndex = i + j - HalfPeriod;
        // border type is used "reflect": (d c b a | a b c d | d c b a) 
        if (dataIndex < 0) {
            dataIndex = -dataIndex - 1;
        } else if (dataIndex >= dataSize) {
            dataIndex = dataSize - (2* (dataIndex - dataSize) + 1);
        }
        output[i] += input[dataIndex] * filter[j];
    }
  }
}
0

2Answer

2の実装の場合、ApplyFilter 1回目の呼び出しで output 配列に値が書き込まれます。2回目の呼び出しでその output 配列を ApplyFilter に渡し、各要素にさらに加算するので、間違った値になります。

「新しく参照している」というのがどういう意味か分かりませんが、 ApplyFilter の呼び出しのたびに output の内容がリセットされるとか新しい配列が用意されるというようにイメージしているなら、それは正しくありません。

処理の流れを今現在どうイメージしているか詳しく説明していただければ、どこでつまずいているか指摘できると思います。

1Like

Comments

  1. @hamua

    Questioner

     ApplyFilter(input, output1, filter, windowSize, dataSize);  
     ApplyFilter(input, output2, filter, windowSize, dataSize);
    

    回答ありがとうございます。
    2)の場合、上記のようにしても間違った値になるのは、
    関数内のoutputを加算していくので、output1とoutput2を間違った値になるということですか?

今回、ポインタを配列と同じように扱ってはなぜ駄目か教えて頂きたいです。

駄目じゃないと思います。

1)一時変数sumを利用。

での

 float sum = 0;

に相当する処理が

2)直接outputに累積加算。

に存在しないから結果が異なってるのではないでしょうか?

ChatGPTには「output配列に以前の値が残っている」と返ってきたのですが、
新しく参照しているなぜ以前の値が残るか理解できてないです。

初期化処理が無いので ChatGPTさんは 「以前の値が残っている」と返したのと思います。

2)直接outputに累積加算。

void ApplyFilter(float *input, float *output, float *filter, int windowSize, int dataSize) {
  for (int i = 0; i < dataSize; i++) {
+    output[i] = 0;
    for (int j = 0; j < windowSize; j++) {
        int dataIndex = i + j - HalfPeriod;
        // border type is used "reflect": (d c b a | a b c d | d c b a) 
        if (dataIndex < 0) {
            dataIndex = -dataIndex - 1;
        } else if (dataIndex >= dataSize) {
            dataIndex = dataSize - (2* (dataIndex - dataSize) + 1);
        }
        output[i] += input[dataIndex] * filter[j];
    }
  }
}

たぶんこれで、同じ値になると思います。

0Like

Your answer might help someone💌