プロが教えるわが家の防犯対策術!

シグマの計算が良く分からなくなってしまいました。。

p = Σ(x_i*x_i+k)

(k=1~10)で、Σは(i=1~n-k)です。(見難くてすみません…)

それで、nを2000000として計算したいので、全部は配列などに入れられないので、
x_iを10個ずつ配列に入れながら足していきたいのですが…

どうすれば出来るか、紙に色々書いたりしているのですが考えつきません(>_<)

どなたかヒントや考え方を教えてください!!
お願いしますm(__)m

A 回答 (8件)

>自分のプログラムでmallocを使うとエラー?になってしまいました。



「エラー?」ではわかりません。横着せずに「正確」に書いて下さい。
コンパイルエラーが出て自分で対処できないという事であれば、そのエラーメッセージを張り付けるくらいの事はするものです。
関数や変数の宣言部分もいいかげん省略したままですが、出せる情報をすべて出すのが、人に協力を求める時の基本です。

>x = (double *)malloc(sizeof(double) * N);

これでコンパイルエラーが出るとしたら、x が double * 型ではないか、mallocを呼び出すための stdlib.hがインクルードされていないか、N が不正な値であるかのどれかです。
stdlib.h は malloc.h でもかまいません。

>コンパイラはBorland C++5.5を使っています。LSI C86でもエラーが出ました。

コンパイラはBorland C++5.5で問題ないです。
LSI C86は16bitコンパイラなので、この場合は役者不足です。

この回答への補足

コンパイルエラーではないので、何も書けませんでした。
コンパイルは出来ますが実行するとエラーになります。

プログラムですが、下の方で判定しているのは課題なのであまり気にしないで下さい(^-^;)

#include<stdio.h>
#include<math.h>
#include<stdlib.h>
#define N 200000

int main(void)
{
unsigned long mkrandom(unsigned long a, unsigned long c, unsigned long x0);

double p[10], t, sigpk, *x;
unsigned long a, c, x0;
int i, k;

x = (double *)malloc(sizeof(double) * N);

if(x == NULL){
printf("mallocに失敗\n");
return -1;
}

for(i=0 ; i<N ; i++){
x[i]=0.0;
}

/*
printf("x0: "); scanf("%d", x);
printf("a: "); scanf("%d", &a);
printf("c: "); scanf("%d", &c);
*/
x[0] = 1; a = 61; c = 49;

x0 = x[0];

for(i=2 ; i<=N ; i++){
x0 = mkrandom(a, c, x0);
x[i-2] = x0 / (double) 4294967296;
/*printf("x[] = %f\n", x[i-2]);*/
}


for(k = 1; k <= 10; k++){
p[k-1] = 0.0;
sigpk = 0.0;
for(i=1; i<=N-k ; i++){
sigpk += (double)x[i-2]*x[i-2 +k];
p[k-1] = 12.0/N*sigpk - 3;
}
}

for(k = 1; k <= 10; k++){
t = sqrt(N-2)*p[k-1]/sqrt(1 - pow(p[k-1], 2));
printf("P_%d = %f, t = %f", k, p[k-1], t);

if(t < 2.326){
printf(" --> 受容");
}
else{
printf(" --> 棄却");
}
printf("\n");
}
free(x);
return 0;
}

unsigned long mkrandom(unsigned long a, unsigned long c, unsigned long x0){
return a*x0 + c;
}

補足日時:2007/05/06 02:19
    • good
    • 0

ANo.6です。



>そうなんですが、乱数列を発生させて配列にXiを入れつつΣ(相関係数)を計算していくのが分かりません(>_<)

そんなバカげた事を言われても、それは質問者さんの課題ですとしか言えません。

>なので、配列を2000000こ分でやってみようかと思いましたが、
>20000までしかできませんでした(^_^;)

この配列の型がdoubleだとしても、必要なメモリは16MB程度なので、使えない事もないと思います。OSとコンパイラは何を使用していますか?
あと、配列の確保の仕方が気になります。ある程度より大きなメモリはmallocやnewでしか確保できない事があります。
#include <stdio.h>
#include <stdlib.h>
#define N 2000000
typedef double x_type;
int main()
{
x_type *x;
int i;
x = (double*)malloc(sizeof(x_type) * N);
if (x == NULL) {
printf("mallocに失敗\n");
return -1;
}
for (i = 0; i < N; i++) {
x[i] = 0.0;
}
printf("mallocと初期化に成功\n");
free(x);
return 0;
}

これを実行できれば解決ですね。
    • good
    • 0
この回答へのお礼

inthefloiさんが書かれたプログラムでは成功しましたが、
自分のプログラムでmallocを使うとエラー?になってしまいました。
OSはWindowsXPで、コンパイラはBorland C++5.5を使っています。LSI C86でもエラーが出ました。

ちなみに、下のようにしました・・・・

x = (double *)malloc(sizeof(double) * N);

if(x == NULL){
printf("mallocに失敗\n");
return -1;
}

for(i=0 ; i<N ; i++){
x[i]=0.0;
}
x[0] = 1; a = 61; c = 49;

x0 = x[0];

for(i=2 ; i<=N ; i++){
x0 = mkrandom(a, c, x0);
x[i-2] = x0 / (double) 4294967296;
/*printf("x[] = %f\n", x[i-2]);*/
}


for(k = 1; k <= 10; k++){
p[k-1] = 0.0;
sigpk = 0.0;
for(i=1; i<=N-k ; i++){
sigpk += (double)x[i-2]*x[i-2 +k];
p[k-1] = 12.0/N*sigpk - 3;
}
}

お礼日時:2007/05/05 18:19

ANo.4です。



>sigpk += late[i]*late[i+k];

まず sigp[k] を求めて、その後に相関係数を出すという課題ではないのですか?

回答者は超能力者ではないので、わからないと言われても、何がわからないのかわかりませんよ。

この回答への補足

そうなんですが、乱数列を発生させて配列にXiを入れつつΣ(相関係数)を計算していくのが分かりません(>_<)

なので、配列を2000000こ分でやってみようかと思いましたが、
20000までしかできませんでした(^_^;)

for(k = 1; k <= 10; k++){
p[k-1] = 0.0;
sigpk = 0.0;
for(i=1; i<=N-k ; i++)
sigpk += (double)x[i-2]*x[i-2 +k];
p[k-1] = 12.0/N*sigpk - 3;
}

補足日時:2007/05/04 00:42
    • good
    • 0

要素数がn個の乱数列はどのように与えられるのでしょうか。


自分でプログラム中で生成してOK?
それともファイルか標準入力あたりからもらってくるのでしょうか?

仮にファイルだとすれば、
sum = 0;
for(i=1; i<n-k; i++){
 xi = ReadFromFile(i);
 xj = ReadFromFile(i+k);
 sum += xi * xj; // Σ(x_i*x_i+k)
}
こんなんで和が求まりますね。
(ReadFromFileは与えられるデータファイルがカンマ区切りかタブ区切りかにあわせて、適当な関数を作って補ってください。)
    • good
    • 0
この回答へのお礼

乱数列は線形合同法で生成します。
関数を使ってるんですが、forが多くなってしまってよくわからない状態です(^_^;)

お礼日時:2007/05/01 18:52

なるほど。

乱数をk個保存しておく必要があるのですね。
ベタに書きますが、例えば、k が 5 だとして、k + 1 要素の配列 buff があるとします。

buff[5] = buff[4];
buff[4] = buff[3];
buff[3] = buff[2];
buff[2] = buff[1];
buff[1] = buff[0];
buff[0] = 次の乱数();

このように配列の中身を1つぶんずらしながら次の乱数を取得していけば、「常に」今取得した乱数は buff[0] に、5つ前の乱数は buff[5] にある事になります。
ただし、最初の5回は5つ前の値が無いので、最初だけ乱数を6回取得する必要があります。
memmoveを使用すれば、ベタに書かずにずらせます。

配列が大きい場合にはリングバッファの方が効率が良いですが、気になったら調べてみて下さい。C++ なら std::deque を使います。
    • good
    • 0
この回答へのお礼

ありがとうございます!
inthefloiさんの考え方は分かったのですが、
なかなかプログラムとして書けません(^_^;)

for(j=0 ; j<10 ; j++){
x0 = random_g(x0, a, c);
tmp = x0 / (double)4294967296;
late[j] = tmp;
}

for(k=1 ; k<=10 ; k++){
for(i=1 ; i<=n-k ; i++){
for(j=9; 0<j ; j--){
late[j] = late[j-1];
}
x0 = random_g(x0, a, c);
tmp = x0 / (double)4294967296;
late[0] = tmp;

sigpk += late[i]*late[i+k];
printf("%f\n", sigpk);

}

}

お礼日時:2007/05/01 18:50

x_i がわからないと計算できませんが、iが決まればXiがきまるんですか?


だったら式を示してください。
それとも、ファイルに入ってるのでしょうか?

なお、n=2000000だったら、いまどきのコンピュータなら配列に入りますよ。
配列に入れるのが正しい計算方法だとは思えませんが。

この回答への補足

これは問題の一部だったのですが、xは乱数列です。

n個の乱数列x_1…x_nが与えられて、
k個ずらした数の組
(x_1, x_1+k), (x_2, x_2+k)…(x_n-k, x_n)
から計算されるそうかん係数を求めたかったんです。。

わかりにくくてすみません(^_^;)

補足日時:2007/04/29 20:04
    • good
    • 0

なぜ配列に入れる必要があるのでしょうか。


p = 0;
としてから、pに足していくだけではダメなのですか?
intでは足りないというのならわかるのですが。

この回答への補足

必要、というか配列が10こくらいないと無理かなと考えたので…。

補足日時:2007/04/29 20:03
    • good
    • 0

言語が何にせよプログラムを書くならfor/while等のループは基本です

この回答への補足

すみません。
それは思いついたんですが、条件やどこで分ければいいかなどですごく迷ってしまいました・・・

補足日時:2007/04/28 23:49
    • good
    • 0

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