dポイントプレゼントキャンペーン実施中!

あるdatファイルに時間と振幅のデータが入っているんですが振幅のデータのみを2乗してから2乗したものに1/2乗し正のものだけから振幅の最大値を求め、振幅の最大値の2割に達した時間を出力したいのですが、どのようにすればよいか分かりません。
サンプルプログラムを載せますのでおねがいします。
ちなみにdatファイルには
時間 振幅
時間 振幅

となっています。
#include <stdio.h>
int main(void) {
const char * fname = "C2.dat";
char line[BUFSIZ];
double amp, time,arrival, max=0,max20;
FILE *fp = fopen(fname, "r");
while (fgets(line, BUFSIZ, fp)) {
sscanf(line, "%lf%lf", &time, &amp);
if (amp > max) {
max = amp;
}
}
fclose(fp);
printf("max: %.7lf\n", max);

fp =fopen(fname,"r");
while (fgets(line, BUFSIZ, fp)){
sscanf(line, "%lf%lf" , &time, &amp);
if(amp > max*0.2){
arrival = time;
break;
}
}
fclose(fp);
printf("arrival:%.16lf\n",arrival);

return 0;
}

A 回答 (4件)

振幅の最大値を求める計算は、2乗してから1/2乗して正の値で比較するってことは、単純に振幅値がマイナスのときはマイナス1をかけて正の値にして比較すれば良さそうだけど。

C言語仕様書なりで数学関数を調べておけば、累乗、平方根を求めるときに使う関数はわかるよね。

まず、振幅の最大値を求める。これは、最大値を代入する変数を用意して、初期値0か負の値で初期化しておいて、一行ずつ読み込んでは比較用の正の値に直した振幅値と比べて読み込んだほうが大きければ最大値用の変数に代入。という繰り返し処理で、ファイルの終わりに到達したら繰り返し処理を終了。

次に、振幅の最大値の2割に達した時間を求める。たぶんぴったり2割という値じゃないときもありそうだから、振幅の最大値の2割以上で最小値になる時間を求めることになるだろう。最小値を求める変数を用意して、振幅の最大値かその変数のデータ型でとりうる最大値で初期化しておいて、ファイルの先頭から一行ずつ読み込んでは、振幅の値が振幅の最大値の2割以上だったら最小値の変数と比較して、最小値の変数の値のほうが大きければ最小値の変数へ代入して更新。並行して、振幅の最大値の2割に達した時間を代入しておく変数の値も更新とともに出力。これをファイルの終わりまで繰り返し。

ひとつの振幅周期しかファイルに記録されていなければ、こんな感じで処理できると思うよ。

構造体、構造体を入れる配列、クイックソートを勉強すると、もっとうまく処理できるプログラムになるだろう。

ほかに細かな注意事項を挙げておくと、変数のデータ型、特に数値データ型は表現できる値の下限値、上限値、オーバーフロー、アンダーフローに注意。また、異なる数値データ型での型変換(cast)で情報落ちしないかに注意。
ファイル操作では、ファイルのオープン、クローズ、読み込み、書き込みのときにエラーが起きたときの処理も追加するのが安全。ファイルを作ったOS 環境とプログラムを動かすOS 環境とで文字コードの違いがないか、改行コードの違いがないか、ファイル先頭のBOM情報に適した処理にしなくてはならないのか注意。エスケープシークエンス文字の使い方にも注意。時間データ値が数値データなのか、文字列データなのか、時間データと振幅データを区切るのはTABコードなのかホワイトスペースなのかなど。

サンプルプログラムはパッと見、arrival 変数が振幅の最大値の2割を超えていればどんどん更新され続けるバグがある。ほかに、sscanf の書式指定で、時間データと振幅データを区切るセパレータ文字列の扱いが抜けているから、正しい振幅データがamp 変数に取り込めていなそう。この辺は、デバッガを使って変数の値をトレースするやり方を身につけるか、デバッグ用のprintfを付け足して確認するのがいいでしょう。
    • good
    • 0

おそらくは、


http://oshiete.goo.ne.jp/qa/8756335.html
からの続きだと思います。

で、想像すると、

・振幅データには、正のものと負のものがある。
・上記の質問の方法では、負のデータは対応できない
・振幅の絶対値を取って、処理する必要がある
・ちなみに、絶対値をとる方法(のひとつ)は、自乗してから、開平すること。

という流れなのかなという。

で、この通りなら、既に回答がありますが、fabs() という関数で絶対値がとれます。
amp の値が決まった直後(入力された後)に、amp = fabs(amp); としておけば良いです。
(最大値を求める方も、0.2倍を超えたか判断する方も)

※ fabs() を使うには、math.h が必要

でも、振幅データだと、複数の波のデータがあると思うのですが、一回の処理でOKなのかな。
    • good
    • 0

計算プログラムなら、まずは、数式にしてみましょう。



もともと計算するために作られたのがコンピュータで、その制御用に作られたのがプログラミング言語です。
ほとんどの言語では、数式をそのまま、あるいは少し変えるだけで表現できるように作られています。

> 振幅のデータのみを2乗してから2乗したものに1/2乗し正のものだけから振幅の最大値を求め

言葉からだけでは判断が難しいです。
ファイルの振幅データは、変数ampに格納されている、というのは理解できていますね?
ならば、上で「最大値」を求めたい「値」って何なのですか?
val = sqrt( amp * amp ) /* ampの2乗の1/2乗(sqrtは非負の引数から√を求める標準関数) */
val = sqrt( amp * amp * amp * amp ) /*「2乗してから2乗したもの」=4乗とも解釈できる */

また「正のもの」とは?amp > 0 の意味ですか、 val > 0 の意味ですか?
ampが実数なので、 √(amp*amp) は非負ですが。
さらに言えば、 「val = ampの絶対値 」ではありませんか?
実数の絶対値を求めるfabsという関数がありますし、自作も簡単です。
    • good
    • 0

プログラムにする以前の問題として, 何をどう計算したいのかがさっぱりわからない.

    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!