質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

Q&A

解決済

2回答

2597閲覧

C言語 偏差値を求める問題

mikan_555

総合スコア15

C

C言語は、1972年にAT&Tベル研究所の、デニス・リッチーが主体となって作成したプログラミング言語です。 B言語の後継言語として開発されたことからC言語と命名。そのため、表記法などはB言語やALGOLに近いとされています。 Cの拡張版であるC++言語とともに、現在世界中でもっとも普及されているプログラミング言語です。

0グッド

1クリップ

投稿2018/12/18 13:38

C言語 偏差値を求める問題

0-10点の間でランダムに点数を発生させて平均値、最高値、標準偏差を求め、点数をソートして表示させるプログラムをc言語で作っています。

エラーメッセージは出ていないのですが、偏差値を正しく出力できません。
原因を教えていただきたいです。よろしくお願いします。

発生している問題・エラーメッセージ

3点 4点 10点 の偏差値がほぼ等しくなってしまうなど、正しく表示することができません。

実行結果 score,standard score 2 32.679492 3 55.772837 4 55.772879 10 55.774792 max: 10 ave: 4.750000

該当のソースコード

偏差値を求める関数 calc_deviation_score()

c

1 2#include <stdio.h> 3#include <stdlib.h> 4#include <time.h> 5#include <math.h> 6 7void set_array_rand(int n, int* score); 8int find_max_in_array(int n, int* score); 9double calc_ave(int n, int* score); 10int calc_sum(int n, int* score); 11void swap(int *a, int *b); 12void bubble_sort(int n, int *score); 13void print_array(int n, int* a); 14double calc_deviation_score(int n, int* score, int ten); 15 16#define N 4 17 18int main(void) 19{ 20 int i, id, max ; 21 int score[N]; 22 double ave; 23 24 printf("score,standard score \n"); 25 26 27 set_array_rand(N, score); 28 bubble_sort(N, score); /* sort here */ 29 print_array(N, score); 30 31 32 id = find_max_in_array(N, score); 33 max = score[id]; 34 ave = calc_ave(N, score); 35 printf("max: %d \n", max); 36 printf("ave: %f \n", ave); 37 38} 39 40 41/*random score */ 42void set_array_rand(int n, int* score) 43{ 44 int i; 45 srand((unsigned int)time(NULL)); 46 for (i = 0; i < n; i++) 47 { 48 score[i] = rand() % 11; 49 } 50} 51 52/* deviation_score */ 53double calc_deviation_score(int n, int* score, int ten) 54{ 55 int i; 56 double hensa; 57 double hensa2_array[N]; 58 double hensati; 59 60 double hensa2_ave; 61 double hensa2_sum = 0; 62 63 64 for (i = 0; i < n; i++) 65 { 66 hensa = score[i] - calc_ave(N, score); 67 hensa2_array[i] = hensa * hensa; 68 } 69 70 71 for(i = 0; i <= n-1 ; i++){ 72 hensa2_sum = hensa2_sum + hensa2_array[i]; 73 } 74 hensa2_ave = (double)hensa2_sum / n; 75 76 77 hensati = (( ten - calc_ave(N, score) ) / sqrt(hensa2_ave)) * 10 + 50; 78 79 return hensati; 80} 81 82 83 84/* print_array */ 85void print_array(int n, int* a) 86{ 87 int i; 88 int score[N]; 89 for (i = 0; i < n; i++){ 90 printf("%d ", a[i]); 91 printf("%f", calc_deviation_score(N, score, score[i])); 92 printf("\n"); 93 } 94 95} 96 97 98/* max */ 99int find_max_in_array(int n, int* score) 100{ 101 int id = 0; 102 int max = score[0]; 103 int i; 104 for (i = 1; i < n ; i++) { 105 if (score[i] > max ) { 106 id =i ; 107 max = score[id]; 108 } 109 } 110 return id; 111} 112 113 114 115/* average */ 116double calc_ave(int n, int* score) 117{ 118 int i; 119 int sum_score = 0; 120 double ave_score; 121 122 for(i = 0; i <= n-1 ; i++){ 123 sum_score = sum_score + score[i]; 124 } 125 ave_score = (double)sum_score / n; 126 return ave_score; 127} 128 129 130/* swap */ 131void swap(int *a, int *b) 132{ 133 int c; 134 c = *b; 135 *b = *a; 136 *a = c; 137} 138 139 140/* sort */ 141void bubble_sort(int n, int *score) 142{ 143 int i, j; 144 for (i = n-1; i > 0; i-- ){ 145 for (j = 0; j < i; j++ ){ 146 if (score[j] > score[j+1]) 147 swap(&score[j] , &score[j+1]); 148 } 149 } 150} 151

試したこと

点数の配列をランダムではなく自分で指定する方法のプログラムを作ったところ正しい偏差値が表示されたので、偏差値を求める関数calc_deviation_score() とその中で呼び出す関数 calc_ave() の式自体には問題はないかと思われます。

c

1#include <stdio.h> 2#include <stdlib.h> 3#include <math.h> 4#define N 5 5 6double calc_deviation_score(int n, int* score, int ten); 7double calc_ave(int n, int* score); 8 9 10int main(void) 11{ 12 int i; 13 int score[5]; 14 15 score[0] = 1; 16 score[1] = 4; 17 score[2] = 5; 18 score[3] = 8; 19 score[4] = 8; 20 21 for (i = 0; i < 5; i++){ 22 printf("%d ", score[i]); 23 printf("%f", calc_deviation_score(N, score, score[i])); 24 printf("\n"); 25 } 26 27 return 0; 28} 29 30 31 32/* deviation_score */ 33double calc_deviation_score(int n, int* score, int ten) 34{ 35 int i; 36 double hensa; 37 double hensa2_array[N]; 38 double hensati; 39 40 double hensa2_ave; 41 double hensa2_sum = 0; 42 43 44 for (i = 0; i < n; i++) 45 { 46 hensa = score[i] - calc_ave(N, score); 47 hensa2_array[i] = hensa * hensa; 48 } 49 50 51 for(i = 0; i <= n-1 ; i++){ 52 hensa2_sum = hensa2_sum + hensa2_array[i]; 53 } 54 hensa2_ave = (double)hensa2_sum / n; 55 56 57 hensati = (( ten - calc_ave(N, score) ) / sqrt(hensa2_ave)) * 10 + 50; 58 59 return hensati; 60} 61 62 63/* average */ 64double calc_ave(int n, int* score) 65{ 66 int i; 67 int sum_score = 0; 68 double ave_score; 69 70 for(i = 0; i <= n-1 ; i++){ 71 sum_score = sum_score + score[i]; 72 } 73 ave_score = (double)sum_score / n; 74 return ave_score; 75} 76 77

実行結果は以下の通りです。
(点数 標準偏差 の順に表示しています。)

1 34.079941 4 45.451412 5 49.241902 8 60.613373 8 60.613373

同様にscore[1]=8 score[3]=4 などscoreの順番を入れ替えて宣言してからバブルソートの関数をかませても同様の結果が得られました。

点数をランダムで作るアルゴリズムが原因でおかしくなってしまったのでしょうか。

補足情報

はじめは[点数][偏差値]の二次元配列を作ることを考えたのですが、まだ授業でポインタについて詳しくやっておらずほかの関数で呼び出す方法が難しそうだったため上のようなやり方で行いました。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

print_array()関数が間違っています。
未初期化のローカル変数score[i]がprintf()関数に渡されてますよ。
※標準偏差の結果が正しいかどうかは分かりません。

投稿2018/12/18 14:08

TaroToyotomi

総合スコア1430

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mikan_555

2018/12/18 15:28

ご回答ありがとうございます。 頂いたコメントをもとに print_array()関数を直してみて実行したところ、それらしい値が得られました。下の記述で初期化できているのでしょうか?? もし直したほうが良い記述があれば今後の勉強のためアドバイスを頂けたら幸いです。 /* print_array */ void print_array(int n, int* a) { int i; int ten = 0; for (i = 0; i < n; i++){ printf("%d ", a[i]); ten = a[i]; printf("%f", calc_deviation_score(N, a, ten)); printf("\n"); } }
TaroToyotomi

2018/12/19 09:52

修正後のコードで問題ないと思います。 あとは、間違いではないですがcalc_deviation_score()関数の中で何回もcalc_ave()を呼び出していますよね。これは無駄だと思います。平均値の計算は1回やれば十分ですよね。
mikan_555

2018/12/19 16:14

ご指摘ありがとうございます!プログラムを改良して無事完成させることができました。 最近c言語を始めたばかりでポインタや初期化などは以前扱っていた言語(python)ではあまり気にしていなかった部分だったので、自分では間違いに気づけなかったため本当に助かりました。ありがとうございました!
guest

0

回答ではありませんが、、、

偏差値ってなんでしたっけ?
確か、点数の分布が正規分布になる場合に意味を持つものでなかったでしょうか?
そうすると、0..10 の乱数を点数として場合、標準偏差が定義できるのでしょうか?
点数を事前に用意した場合、偏った分布になるので、それらしい結果が得られると思います。

投稿2018/12/18 14:01

pepperleaf

総合スコア6383

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

mikan_555

2018/12/18 15:39

コメントありがとうございます。 偏差値は平均点を50としたときに自分の点がどのくらいの値になるかで定義の式があるみたいです。 調べてでてきた式をそのまま使いましたがおそらく正規分布じゃなくても値自体は出せるようです。 ただ、今回は乱数を用いて点数を生成したため、値を出しただけでおっしゃる通り出力した偏差値自体から何か推測できるなどの統計学的な意味は持たないと思います。
episteme

2018/12/19 10:14

正規分布する乱数食わせてみればいいよ。単純にはN個の一様乱数の平均を取ればNを大きくすると正規分布する。
pepperleaf

2018/12/19 14:23

確かに、正規分布する乱数を食わしてみれば、良いですね。 なお、計算式のみは、ざっと見た限り、そんなもんて感じでした。 平均を取って、それぞれの点数と平均の差の二乗。 (ただ、毎回、平均の計算してるのは無駄っぽいですが) そういう意味では、計算は合っている? (他にも問題はあるとの事ですが)
mikan_555

2018/12/19 16:28

正規分布する乱数を生成する方法があるのですね。(実を言うと今回作成した乱数発生の関数は授業時に与えられたサンプルの数値を少しいじっただけで仕組みはあまり理解できていないのが現状です) 平均値の関数の呼び出しについてご指摘ありがとうございます。今までは動けばいいかなと思って気にしたことがあまりなかったのですがやはり今後長いプログラムを書くようになることを考えると同じ記述を何度も書くのはよくないですよね、、、 まだまだ勉強不足だなと実感いたしました。 正規分布する乱数についても調べてみようと思います。ありがとうございます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問