Ex12Ans
From Prog0
演習第12回
Contents |
解答例
A問題
A-1 逐次平均
ファイル名: ex12a1.c
#include <stdio.h>
double avg(int, double, double);
int main()
{
double indata, avgdata = 0.0;
int n = 1;
printf("データを入力してください\n");
while(1) {
printf("入力値%d= ", n);
scanf("%lf", &indata);
if(indata == 0.0) break;
avgdata = avg(n, indata, avgdata);
printf("平均値%d= %.1f\n", n, avgdata);
n++;
}
return 0;
}
double avg(int n, double data, double avgdata)
{
return (avgdata*(n-1)+data)/n;
}
A-2 数値の桁数
ファイル名: ex12a2.c
#include <stdio.h>
int digits(int);
int main()
{
int i, j;
printf("正の整数を入力してください:");
scanf("%d", &i);
j = digits(i);
printf("%d の桁数は %d です\n", i, j);
return 0;
}
int digits(int x)
{
int keta = 1;
while (x /= 10)
{
keta++;
}
return keta;
}
A-3 10進数から2進数への変換
ファイル名: ex12a3.c
#include <stdio.h>
#define DIGIT 8
void d2b(int);
int main()
{
int n;
while (1)
{
printf("10進数を入力してください:");
scanf("%d", &n);
if (n < 0)
break;
else if (n >= 256)
printf("256以上の値が入力されました\n");
else
d2b(n);
}
return 0;
}
void d2b(int n)
{
int i, bin[DIGIT];
for (i = 0; i < DIGIT; i++)
{
bin[i] = n % 2;
n /= 2;
}
for (i = 0; i < DIGIT; i++)
printf("%d", bin[DIGIT - 1 - i]);
printf("\n");
}
/* 注:配列の使い方は、ハンドアウトLec12-24ページのようにこのプログラムと反対向きでもよい。
またハンドアウトでは32bitだが、本問では入力255までなので、8bitで十分。 */
B問題
B-1 ニュートン法
ファイル名: ex12b1.c
#include <stdio.h>
#include <math.h>
#define EPS 1.0e-6
double f(double);
double df(double);
int main()
{
double x, fx, dfx;
x = 3.0;
printf("x(k-1)\t\tfx\t\tdfx\t\tx(k)\t\tf(x)\n");
while((fx = f(x)) > EPS ) {
dfx = df(x);
printf("%f\t%f\t%f\t", x, fx, dfx);
x = x - fx/dfx;
printf("%f\t%f\n", x, f(x));
}
printf("x = %f\n", x);
return 0;
}
double f(double x)
{
return exp(x) - 4.0*x;
}
double df(double x)
{
return exp(x) - 4.0;
}
B-2 四捨五入
ファイル名: ex12b2.c
#include <stdio.h>
double round_to(double, int); // プロトタイプ宣言
int main()
{
double val, rounded;
int n;
printf("正の実数を入力してください:");
scanf("%lf", &val);
printf("小数点以下の桁数を入力してください:");
scanf("%d", &n);
rounded = round_to(val, n);
printf("%f\n", rounded);
return 0;
}
/* xを四捨五入して小数点以下n桁までにする */
double round_to(double x, int n)
{
double mul = 1, result;
int i;
for (i = 0; i < n; i++) // 10のn乗を求める
mul *= 10;
result = (int)(x * mul + 0.5) / mul; // 四捨五入
return result; // resultの値を戻り値として返す
}
B-3 各桁の数値の和
ファイル名: ex12b3.c
#include <stdio.h>
#include <stdlib.h>
int digits(int);
int get_1_digit(int, int);
int main()
{
int i, val, total = 0;
printf("正の整数を入力してください:");
scanf("%d", &val);
if (val < 0)
{
fprintf(stderr, "不正な値が入力されました\n");
exit(8);
}
for (i = 1; i <= digits(val); i++)
total += get_1_digit(val, i);
printf("%d の各桁の数値の和は %d です\n", val, total);
return 0;
}
/* ハンドアウトの解 */
int digits(int x)
{
int keta = 0;
while (x > 0)
{
x /= 10;
keta++;
}
return keta;
}
/* 別解
int digits(int x)
{
int keta = 1, y = 10;
while ((x / y) > 0)
{
y *= 10;
keta++;
}
return keta;
}
*/
/* ハンドアウトの解 */
int get_1_digit(int x, int pos)
{
int i, j;
for (i = 1; i < pos; i++)
x /= 10;
j = x % 10;
return j;
}
/* 別解
int get_1_digit(int x, int pos)
{
int i, j, k = 1;
for (i = 1; i < pos; i++)
{
k *= 10;
}
j = x % (k * 10) / k;
return j;
}
*/
Extra問題
E-1 素数判定
ファイル名: ex12e1.c
#include <stdio.h>
#define NUM 1000
int isprime(int);
int main()
{
int i, p = 0;
for(i = 2; i <= NUM; i++)
{
if(isprime(i))
{
printf("%4d ", i);
p++;
if(p%10 == 0) printf("\n"); /* 10個表示したら改行 */
}
}
printf("\n");
return 0;
}
/* 素数を判定するアルゴリズムには様々な方法があり、性能も異なります。以下に2つの方法を示します。 */
int isprime(int d)
{
int i;
if(d == 2) return 1; /* 2は素数 */
if(d%2 == 0) return 0; /* 2以外の2で割り切れるものは非素数 */
/* 方法1:3からd/2までの奇数で割り切れるかを調査 */
for(i = 3; i < d/2; i += 2)
{
if(d%i == 0) return 0; /* 割り切れたので非素数 */
}
/* 方法2:dは、その平方根より大きな数で初めて割り切れることはないため、3からdの平方根までの奇数を調査(方法1より高速) */
/*
for(i = 3; i*i <= d; i += 2)
{
if(d%i == 0) return 0;
}
*/
return 1; /* 割り切れなかったので素数 */
}
