
コンパイラは通ったのですが、自分の思うように処理されない箇所があって困っています。
1区間の数字列を回帰直線で近似し、回帰直線との誤差が最大の点で区間を分割(誤差が閾値以上なら)するプログラムを作っています。次に分割した区間それぞれに同様の作業をし、分割が一つでもあればまた最初から繰り返す、どこも分割されなければ終了・・・という流れです。
プログラムでは
do{
bunkatu=0;
for(全ての区間){
(最大誤差や回帰直線の傾きを0に初期化する)
(傾き、最大誤差求める)
if(最大誤差が閾値以上なら){
(最大誤差の点を境に区間を分けるよう設定)
bunkatu = 1;}
}
}while((bunkatu) != 0);
と表しています。分割が一つでもあれば変数 bunkatu が1になり、whileの条件 (bunkatu) != 0 と合っているのでまた do 以下から動作する・・・と考えているのですが、考え方としてはこれで合っているのでしょうか。
A 回答 (5件)
- 最新から表示
- 回答順に表示
No.5
- 回答日時:
#1さんの質問に『調べたところ回数が延々と出力され、10数万いったぐらいで「セグメントエラー」が起こりプログラムが終了しました。
for文から抜け出していないと思われますが、どうしてそうなるかが検討がつかない状態です。』と返答されているので、#4さんが回答しておられるように、設定配列要素数より大きな値(あるいは小さな値)をもって配列をアクセスしたことによるセグメンテーション違反のエラーです。しかし、提示されたプログラムにそのような配列要素を変えるようなプログラム箇所はありません。すなわち、Kaikia(), Kaikib(), Gosa(), Point() のいずれかに配列要素を換えるようなプログラム部分を持っているものと思われます。そのプログラムの配列要素を決めるやり方をしている関数とその箇所を見つけて訂正して下さい。考えられるのは
i=(int)実数計算式
をもって int型の配列要素としているアルゴリズムを使っている場合です。
なお、近似プログラムにおいて10数万も繰り返すことは、解のない発散状態にあることを示しています。よって、アルゴリズムの見直しも必要と考えます。
No.4
- 回答日時:
> 調べたところ回数が延々と出力され、10数万いったぐらいで「セグメントエラー」が起こりプログラムが終了
はっきり言って、これはまともな動作ではありませんので、どこかでメモリ破壊を起こしていると推測します。
メモリ破壊とは何か。
int a[5]; と定義した配列があるとします。この配列には a[0]~a[4] が存在しますが、a[5] = 0; とすれば、この配列以外のメモリを書き変えてしまうことになります。Cは配列の上限チェックを行いません(下限もチェックしない)ので、意図したか否かに関わらず、配列以外のメモリを書き変えることができてしまいます(いわゆるバッファオーバーフロー)。そのメモリは別の変数である可能性大ですから、プログラムの記述とは違う時点でその変数の値が変わってしまいます。こうした事を「メモリ破壊」と呼びます。メモリ破壊があれば、プログラムが思いもよらぬ動きをするのは当然です。
char の変数領域(8bit単位)に int 型(32bitの事が多い)へのポインタで書き込む、int の変数領域に double 型(普通64bit)へのポインタで値を書き込む…等もメモリ破壊を起こします。他に、スタックオーバーフローを起こした、割込処理或いは他のスレッドによって変数が書き変えられた等、いろいろなケースがあります。
大抵の場合、メモリ破壊はプログラムのバグであり、それがどこに潜んでいるか簡単に見当がつくようなものではありませんが、バグがあるかもしれないという目で提示されたコードを眺めてみると、気になる所がいくつかあります。特に for 文の回し方がそうです。
例えば、次の for 文。
for (o = all; o >= 0; o--) { ...
上記の int a[5]; について for ループを回すとしたら、例えば
for (o = 4; o >= 0; o--) { a[o] = 何か; }
のように回すことができますが、配列のサイズが5だからと言って
for (o = 5; o >= 0; o--) { a[o] = 何か; }
と回したなら、本来存在しないはずの a[5] を書き変えてしまいます。これを連想してしまうのです。要するにバッファオーバーフローです。
他にも
・E[h] = E[h - 1]; の E[h - 1] が配列の外(E[-1])をアクセスする事はないか
・E[o + 1] = E[o]; の E[o + 1] は大丈夫か、等々
念のために言えば、これらが誤りだと断定しているのではありません。提示されたコードはプログラムのほんの一部分でしかなく、ここに至るまでの経緯がわかりませんから、この回し方で正しいかもしれませんし、もちろん他のコードがメモリを破壊している可能性もあります。疑いの目で見ないとバグの手がかりは得られないという事なのです。
No.3
- 回答日時:
bunkatu=0; のような初期化をループの中で行ったため、値が毎回リセットされループの脱出条件がいつまでも満足しないと言うようなミスを犯しやすい。
doやforループにそのような事がないか点検してみたらどうですか。
符号無し整数なのに負数になったら脱出というミスも有ります。
命令を削って無限ループの原因を探る事です。
No.2
- 回答日時:
可能な限り、「ソースそのもの」を提示するようにしてください。
この回答への補足
do{
bunkatu=0;
all=kaisuu;
for(o=all; o>=0; o--){
katamuki=0.0;
seppen=0.0;
point=0;
maxgosa=0.0;
katamuki = Kaikia(S[o],E[o],x);
seppen = Kaikib(S[o],E[o],x);
if(E[o]-S[o] > 21){
maxgosa = Gosa(S[o],E[o],katamuki,seppen,x);
if (maxgosa > 50.0){
point = Point(S[o],E[o],katamuki,seppen,x);
for(h=all; h>=o; h--){
if(h>o){
E[h]=E[h-1];
S[h]=s[h-1];
}
}
E[o+1]=E[o];
E[o] = point;
S[o+1] = point + 1;
kaisuu++;
printf("%d\n",kaisuu);
bunkatu = 1;}
}
}
}while((bunkatu) != 0);
失礼しました、上が自分のプログラムの質問部分のソースです。
Kaikia : 回帰直線の傾きを出力
Kaikib : 回帰直線の切片を出力
S(tart)[o],E(nd)[o] : 区間の始点と終点の位置
Gosa : 回帰直線と各点の最大誤差を出力
Point : 最大誤差を取る点の位置を出力
S[0]・・・E[0] S[1]・・・・・・・E[1] S[2]・・・E[2]
という区間がある場合、S[1]とE[1]の間で分割が起こると
S[0]・・・E[0] S[1]・ E[1] S[2]・E[2] S[3]・・・E[3]
となるようプログラムしたものです。
お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!
似たような質問が見つかりました
- 統計学 信頼区間についての質問です。 6 2023/06/25 17:34
- 統計学 t検定について教えてください 2 2023/02/23 16:35
- 物理学 測定値と理論値の誤差について 交流回路の実験でRL回路、RC回路、RLC直列回路の周波数を上げた時の 1 2022/05/22 23:37
- Java Java 南京錠 2 2023/02/04 11:46
- 工学 直流モーターを比例制御 積分制御 PI制御で動かすとするとき、入出力波形から求めたそれぞれのゲインと 1 2022/06/30 21:16
- C言語・C++・C# win10で、正確な待ち時間の作り方 6 2023/02/14 18:28
- 大学・短大 C言語線形リストの問題です 3 2022/12/22 00:45
- 物理学 時定数で実験で求めた値と理論値に誤差が生じる理由はなんですか?自分は実験で使用した抵抗やコンデンサの 3 2022/09/26 11:32
- 統計学 直線の傾き(回帰係数)から相関係数を計算できるのでしょうか? 2 2022/09/16 19:28
- 大学受験 国立受験 11月からの大逆転劇を起こすには 7 2022/11/14 19:24
関連するカテゴリからQ&Aを探す
おすすめ情報
デイリーランキングこのカテゴリの人気デイリーQ&Aランキング
-
C言語 配列の長さの上限
-
9枚の写真がA4 1枚に印刷できま...
-
【速いブラインドタッチ】手を...
-
char型配列をString型にしたい
-
電子書籍を見るためにはどうし...
-
配列をEraseしてもメモリが開放...
-
C言語 変換指定%sについてです。
-
多次元配列のポインタ渡し
-
2次元配列を戻り値とする関数?
-
キーボードのキー配列について
-
リスト構造について
-
【VBS】 フォルダ直下のファイ...
-
配列を使わずに、変数名を動的...
-
計算結果がものすごく多いんで...
-
複数のボタンを配列で扱う方法...
-
std::listの代入について
-
配列の参照渡しで型が一致しま...
-
配列と乱数を使ったプログラム
-
配列を含む構造体の初期値について
-
C++ vectorに配列をプッシュしたい
マンスリーランキングこのカテゴリの人気マンスリーQ&Aランキング
-
C言語 配列の長さの上限
-
配列を使わずに、変数名を動的...
-
C# Listを使わずに2次元配列の...
-
【速いブラインドタッチ】手を...
-
配列をEraseしてもメモリが開放...
-
テキストファイルから文字列を...
-
先頭アドレスとは何ですか?
-
配列で格納したものをmsgboxで...
-
複数の選択範囲の行番号を個別...
-
C# 配列の変数宣言について。
-
C++ vectorに配列をプッシュしたい
-
配列を含む構造体の初期値について
-
VBで構造体の配列を関数に渡す...
-
C言語で特定列だけを抽出して配...
-
キーボードのキー配列について
-
ExcelVBAで質問です。離れた二...
-
2次元配列を戻り値とする関数?
-
unsigned char配列への入力の仕方
-
【C言語】配列の中に配列を入れ...
-
Redimした動的配列はEraseする...
おすすめ情報