C言語とのことなので、C++ の機能は仕様せず、書いてみました。
c++ の標準ライブラリを使うと、もう少し完結にかけます。
最小値を計算する
初期値は float 型のとり得る最大の値 FLT_MAX にすればよいです。
c
1/**
2 * @brief 配列の最小値を計算する。
3 * @param array 配列
4 * @param n 配列の長さ
5 * @return 配列の最小値
6 */
7float min(float array[], int n)
8{
9 if (n == 0) // 配列が空の場合
10 return 0;
11
12 float min = FLT_MAX;
13 for (int i = 0; i < n; i++) {
14 if (min > array[i])
15 min = array[i];
16 }
17
18 return min;
19}
最大値を計算する。
初期値は float 型のとり得る最小の値 -FLT_MAX にすればよいです。
c
1/**
2 * @brief 配列の最大値を計算する。
3 * @param array 配列
4 * @param n 配列の長さ
5 * @return 配列の最大値
6 */
7float max(float array[], int n)
8{
9 if (n == 0) // 配列が空の場合
10 return 0;
11
12 float max = -FLT_MAX;
13 for (int i = 0; i < n; i++) {
14 if (max < array[i])
15 max = array[i];
16 }
17
18 return max;
19}
平均、分散、標準偏差を計算する。
- 平均μ = Σ x_i / 入力値の個数
- 分散σ = Σ(x_i - μ)^2 / 入力値の個数
- 標準偏差 = √σ
分散については、分散σ = Σx_i^2 / 入力値の個数 - μ^2 と式変形でき、平均及び分散両方を計算する際には、こちらのほうが計算量が少なくてすみます。
ステップとしては、
- 和 Σx_i、自乗和 Σx_i^2 を計算する。
- μ = Σx_i / n で平均を計算する。
- σ^2 = Σx_i^2 / n - μ^2 を計算する。
- √σ^2 を計算する。
c
1/**
2 * @brief 配列の平均、分散及び標準偏差を計算する。
3 * @param array 配列
4 * @param n 配列の長さ
5 * @param mean 配列の平均
6 * @param var 配列の分散
7 * @param std 配列の標準偏差
8 */
9void mean_var(float array[], int n, float *_mean, float *_var, float *_std)
10{
11 if (n == 0) { // 配列が空の場合
12 *_mean = *_var = *_std = 0;
13 return;
14 }
15
16 // 配列の和および自乗和を計算する。
17 float sum = 0; // 和
18 float squared_sum = 0; // 自乗和
19 for (int i = 0; i < n; i++) {
20 sum += array[i];
21 squared_sum += array[i] * array[i];
22 }
23
24 // 平均、分散、標準偏差を計算する。
25 float mean = sum / n;
26 float var = (squared_sum / n - mean * mean);
27 float std = sqrt(var);
28
29 // ポインタ経由で値を返す。
30 *_mean = mean;
31 *_var = var;
32 *_std = std;
33}
偏差値を計算する。
- 偏差値 = (x - μ) / σ x 10 + 50
c
1
2/**
3 * @brief 偏差値を計算する。
4 * @param array 配列
5 * @param n 配列の長さ
6 * @param mean 配列の平均
7 * @param std 配列の標準偏差
8 * @param std_scores 配列の各要素の偏差値
9 */
10void std_scores(float array[], int n, float mean, float std, float std_scores[])
11{
12 if (n == 0) // 配列が空の場合
13 return;
14
15 for (int i = 0; i < n; i++) {
16 std_scores[i] = 10 * (array[i] - mean) / std + 50;
17 }
18}
19
コード全体
#undef NDEBUG // assert をリリースビルドで実行するため
#include <assert.h>
#include <float.h>
#include <math.h>
#include <stdio.h>
/**
* @brief 配列の最小値を計算する。
* @param array 配列
* @param n 配列の長さ
* @return 配列の最小値
*/
float min(float array[], int n)
{
if (n == 0) // 配列が空の場合
return 0;
float min = FLT_MAX;
for (int i = 0; i < n; i++) {
if (min > array[i])
min = array[i];
}
return min;
}
/**
* @brief 配列の最大値を計算する。
* @param array 配列
* @param n 配列の長さ
* @return 配列の最大値
*/
float max(float array[], int n)
{
if (n == 0) // 配列が空の場合
return 0;
float max = -FLT_MAX;
for (int i = 0; i < n; i++) {
if (max < array[i])
max = array[i];
}
return max;
}
/**
* @brief 配列の平均、分散及び標準偏差を計算する。
* @param array 配列
* @param n 配列の長さ
* @param mean 配列の平均
* @param var 配列の分散
* @param std 配列の標準偏差
*/
void mean_var(float array[], int n, float *_mean, float *_var, float *_std)
{
if (n == 0) { // 配列が空の場合
*_mean = *_var = *_std = 0;
return;
}
// 配列の和および自乗和を計算する。
float sum = 0; // 和
float squared_sum = 0; // 自乗和
for (int i = 0; i < n; i++) {
sum += array[i];
squared_sum += array[i] * array[i];
}
// 平均、分散、標準偏差を計算する。
float mean = sum / n;
float var = (squared_sum / n - mean * mean);
float std = sqrt(var);
// ポインタ経由で値を返す。
*_mean = mean;
*_var = var;
*_std = std;
}
/**
* @brief 偏差値を計算する。
* @param array 配列
* @param n 配列の長さ
* @param mean 配列の平均
* @param std 配列の標準偏差
* @param std_scores 配列の各要素の偏差値
*/
void std_scores(float array[], int n, float mean, float std, float std_scores[])
{
if (n == 0) // 配列が空の場合
return;
for (int i = 0; i < n; i++) {
std_scores[i] = 10 * (array[i] - mean) / std + 50;
}
}
int main()
{
float array[100]; // 入力した数字を格納する配列
float input; // 入力を格納する変数
int n; // 入力した数字の数
while (n < 100) {
printf("Input (%d): ", n);
scanf("%f", &input);
if (input == 0)
break; // 入力終了
array[n++] = input;
printf("%.2f\n", input);
}
float minval = min(array, n); // 最大値を計算する。
float maxval = max(array, n); // 最小値を計算する。
float mean, var, std;
mean_var(array, n, &mean, &var, &std); // 平均、分散、標準偏差を計算する。
float scores[100];
std_scores(
array, n, mean, std, scores); // 配列の各要素の偏差値を計算する。
printf(
"min: %.2f, max: %.2f, mean: %.2f, var: %.2f, std: %.2f\n",
minval,
maxval,
mean,
var,
std);
printf("std scores: ");
for (int i = 0; i < n; i++) {
printf("%.2f ", scores[i]);
}
printf("\n");
// テスト
//////////////////////////////////////////////////
// テストデータ
array[0] = 1.1;
array[1] = 2.5;
array[2] = 4.2;
array[3] = 1.5;
// 最小値、最大値、平均、分散、標準偏差、偏差値を計算する。
minval = min(array, 4);
maxval = max(array, 4);
mean_var(array, 4, &mean, &var, &std);
std_scores(array, 4, mean, std, scores);
// 正解の値と合っているか確認する。
assert(fabs(minval - 1.1) < 0.01);
assert(fabs(maxval - 4.2) < 0.01);
assert(fabs(mean - 2.325) < 0.01);
assert(fabs(var - 1.431) < 0.01);
assert(fabs(std - 1.196) < 0.01);
float expected_scores[] = {39.76, 51.46, 65.66, 43.10};
for (int i = 0; i < 4; i++) {
assert(fabs(scores[i] - expected_scores[i]) < 0.01);
}
return 0;
}