アプリ版:「スタンプのみでお礼する」機能のリリースについて

再度質問させていただきます。
以下のプログラムを実行するとsegmentation faultが出たり出なかったりします。
いまいち原因が分からないので回答お願いします。

ちなみに目的としては、
0~1の乱数が複数個与えられたときに、与えられた乱数を2つのグループに分け、その2グループの差ができるだけ小さくなるようにする。
といったものです。
よろしくお願いします。

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
//染色体の数
#define Number_of_ch 10
//エリート選抜の割合
#define Selection 0.3
//交叉率
#define Cross_ratio 0.7
//突然変異率
#define Mutation_ratio 0.2
//ループ回数
#define Number_of_loop 100


int main(int argc , char *argv[])
{
int f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,x,y,z;
long int Number_of_gene = argc-1;//遺伝子の数
int chromosome[Number_of_ch][Number_of_gene],distmin[Number_of_gene];//染色体と遺伝子
int best_chromosome[Number_of_gene],Number_of_cross=0,ch_1=0,ch_2=0,point=0,temp=0,temp_1=0,temp_2=0,abc=0,loop=0;
double real_Number[Number_of_gene] , dist[Number_of_ch];
double best = 100.0;
double sum0 = 0.0 , sum1 = 0.0 ;

//入力値の記録
for(i=0 ; i<Number_of_gene ; i++){
real_Number[i] = atof(argv[i+1]);
}

srand((unsigned)time(NULL));

//染色体の初期化
for(j=0 ; j<Number_of_ch ; j++){
for(k=0 ; k<Number_of_gene ; k++){
chromosome[j][k] = rand() % 2;//0 or 1のグループ分け
}
}

//----------------------ループ開始------------------------
while(loop < Number_of_loop){

//差分
for(l=0 ; l<Number_of_ch ; l++){
for(m=0 ; m<Number_of_gene ; m++){
if(chromosome[l][m] == 0){
sum0 = sum0 + real_Number[m];
}
else{
sum1 = sum1 + real_Number[m];
}
}
if(sum0 > sum1){
dist[l] = sum0 - sum1;
}
else{
dist[l] = sum1 - sum0;
}
}

//評価と記憶
for(n=0 ; n<Number_of_ch ; n++){
if(dist[n] < best){
best = dist[n];
for(o=0 ; o<Number_of_gene ; o++){
best_chromosome[o] = chromosome[n][o];
}
}
}

//ソート
for(p=0 ; p<Number_of_ch ; p++){
for(q=1 ; q<Number_of_ch-p+1 ; q++){
if(dist[q-1] > dist[q]){
for(r=0 ; r<Number_of_gene ; r++){
distmin[r] = chromosome[q][r];
chromosome[q][r] = chromosome[q-1][r];
chromosome[q-1][r] = distmin[r];
}
}
}
}

//エリートの選抜
for(s=Number_of_ch*Selection ; s<Number_of_ch ; s++){
for(t=0 ; t<Number_of_gene ; t++){
chromosome[s][t] = best_chromosome[t];
}
}

//交叉
Number_of_cross = Number_of_ch * Cross_ratio;

for(u=0 ; u<Number_of_cross ; u++){
ch_1 = (Number_of_ch-1) * (rand()/32767);
ch_2 = (Number_of_ch-1) * (rand()/32767);
point = (Number_of_gene-1) * (rand()/32767);

for(x=point ; x<Number_of_gene ; x++){
temp_1 = chromosome[ch_1][x];
for(y=0 ; y<Number_of_gene ; y++){
if(chromosome[ch_1][x] == chromosome[ch_2][y]){
temp_2 = chromosome[ch_2][x];
chromosome[ch_2][x] = chromosome[ch_2][y];
chromosome[ch_2][y] = temp_2;
}
for(z=0 ; z<Number_of_gene ; z++){
if(chromosome[ch_2][x] == chromosome[ch_1][z]){
chromosome[ch_1][x] = chromosome[ch_1][z];
chromosome[ch_1][z] = temp_1;
}
}
}
}
}

//突然変異
for(f=0 ; f<Number_of_cross ; f++){
for(g=0 ; g<Number_of_gene ; g++){
if(rand()/32767 < Mutation_ratio){
abc = (Number_of_gene-1) * (rand()/32767);
temp = chromosome[f][g];
chromosome[f][g] = chromosome[f][abc];
chromosome[f][abc] = temp;
}
}
}

loop = loop + 1;

}

//結果の出力
printf("# best = %f \n",best);
for(h=0 ; h<Number_of_gene ; h++){
printf("%d",best_chromosome[h]);
}
printf("\n");

}

A 回答 (3件)

Segmantation Fault は領域外へアクセスしたときに発生するもので、プログラム上の原因は次のようなものがほとんどです


・確保させていない領域にアクセスした
 NULL、freeした後の領域等
・配列の添字が範囲外

ですから、まずは、上記の点問題無いかを調べます。
エラーなくコンパイルできたかどうかは関係ありません。


で、プログラムを全部チェックするのは面倒ですが、それでも、斜め読みでもわかるくらいおかしな点を
http://oshiete.goo.ne.jp/qa/8589069.html
で指摘させていただきましたが、今回のプログラムでもまったく直ってません。


(rand()/32767);
おそらく、[0,1]の乱数を期待しているようですが、2つの理由から、そうはなっていません。
そのことは理解できていますか?
    • good
    • 0
この回答へのお礼

RAND_MAXは理解し、訂正したのですが訂正前のものをのせてしまいました。
無事解決できました。
ありがとうございます。

お礼日時:2014/05/14 01:08

なんというか…いまいち読む気にならないですねぇ……。


# define定義と変数が入り交じる感じで読みにくい。

とりあえず……
>if(rand()/32767 < Mutation_ratio){
>abc = (Number_of_gene-1) * (rand()/32767);
の結果は正常なんですかね?
# abcが0から(Number_of_gene-1)の範囲に間違いなく収まります?


ご使用の環境ではRAND_MAXはいくつなんでしょう?
# 32767というマジックナンバーは…なんでしょう??

ちなみに…私なら除算ではなく剰余を使いますけどね。
abc = rand() % Number_of_gene;
とか。(これならNumber_of_gene以上の値にはならないのでバッファオーバーランしないし)
    • good
    • 0

直接の回答にはなりません。

開発環境のデバック機能を利用して、落ちるところ(直前?)を突き止め、ロードマップなどを参照してどのステートメントかを突き止める。あるいはソースレベルデバッグが可能な開発環境ならさらに楽です。そこの変数を確認、多分、配列の大きさを超えてアクセスしようとしてるのでは。乱数発生で行われているため、毎回同じ結果にならないだけと思います。
    • good
    • 0

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