- p-001.c (SJIS)
p-001.c
#include <stdio.h>
/*
hello : "Hello, World" という文字列を返す
*/
char *hello(void) {
return "Hello, World";
}
/*
print_s : 引数で渡された文字列を表示して改行
*/
void print_s ( char *string ) {
printf ( "*" );
printf ( string ); /* 引数の表示 */
printf ( "\n" ); /* 改行 */
}
/*
* main
*/
int main(void) {
print_s ( "abc" ); /* "*" + "abc" + "\n" */
print_s ( hello() ); /* hello() が "Hello, World"
を返すので.. */
return 0;
}
/*
print_s ( "abc" );
↓
string = "abc" !! "abc" はデータ
print_s ( string );
↓
string = "abc"
{
printf ( "*" );
printf ( string ); /* 引数の表示 */
printf ( "\n" ); /* 改行 */
}
↓
{
printf ( "*" );
printf ( "abc" ); /* 引数の表示 */
printf ( "\n" ); /* 改行 */
}
↓
"abc" "\n" が表示される
---------------------------------------
<誤り>
print_s ( hello() );
↓
string = hello()
print_s ( string );
↓
string = hello() !! hello() 関数呼出しなので Code
!! hello()そのものが渡るのではなく
!! hello() の結果が渡る
{
printf ( "*" ); /* 改行 */
printf ( string ); /* 引数の表示 */
printf ( "\n" ); /* 改行 */
}
↓
{
printf ( "*" ); /* 改行 */
printf ( hello() ); /* 引数の表示 */
printf ( "\n" ); /* 改行 */
}
---------------------------------------
<正しい>
print_s ( hello() );
↓
hello() が呼び出されて、"Hello, World" が返る
それが print_s の引数に置き換わる
print_s ( "Hello, World" );
↓
後は "abc" と同様...
*/
- p-002.c (SJIS)
p-002.c
#include <stdio.h>
#include "s_input.h"
#include "s_print.h"
int main(void) {
s_print_double ( 2.0 ); /* double の出力 */
s_print_string ( " を " );
s_print_double ( 3.0 );
s_print_string ( " で割ると " );
s_print_double ( 2.0/3.0 ); /* double の計算 */
s_print_string ( " になる。" );
return 0;
}
- p-003.c (SJIS)
p-003.c
#include <stdio.h>
#include "s_input.h"
#include "s_print.h"
double sum ( int i, int n, double x ) {
/* sum ( 0, N, X ) は X を N 回、加えたもの */
if ( i < n ) {
return sum ( i + 1, n, x ) + x;
} else {
return 0.0;
}
}
int main(void) {
s_print_double ( sum ( 0, 100, 0.3 ) );
/* 30 になるはず */
s_print_string ( "\n" );
s_print_double ( sum ( 0, 3000, 1.0/3000.0 ) );
/* 1 になるはず */
s_print_string ( "\n" );
return 0;
}
- p-004.c (SJIS)
p-004.c
/*
* f(x)=x^2 を、区間[0,1]で定積分する
*
* 区間 [0,1] を 1000 等分して、短冊を作り、その面積を
* 全て加える
*/
#include <stdio.h>
#include "s_print.h"
/*
f(x)=x^2
*/
double f(double x) {
return x*x;
}
/*
sum ( int k, int n )
\sum_{i=k}^{n-1} S_i
= S_k + \sum_{i=k+1}^{n-1} S_i
= S_k + sum( k+1, n ) 再帰呼出し
*/
double sum ( int k, int n ) {
if ( k < n ) {
return f(0.0 + k * (1.0-0.0)/1000.0)*(1.0/1000.0) + sum(k+1,n);
} else { /* k == n の時は、\sum_{i=n}^{n-1} .. → 0 */
return 0.0;
}
}
int main(void) {
s_print_string ( "x^2 を [0,1] 区間で積分すると " );
s_print_double ( sum ( 0, 1000 ) );
s_print_string ( " になります。\n" );
return 0;
}
- p-005.c (SJIS)
p-005.c
/*
* f(x)=x^2 を、区間[0,1]で定積分する
*
* 区間 [0,1] を 10000 等分して、短冊を作り、その面積を
* 全て加える
*/
#include <stdio.h>
#include "s_print.h"
/*
f(x)=x^2
*/
double f(double x) {
return x*x;
}
/*
sum ( int k, int n )
\sum_{i=k}^{n-1} S_i
= S_k + \sum_{i=k+1}^{n-1} S_i
= S_k + sum( k+1, n ) 再帰呼出し
*/
double sum ( int k, int n ) {
if ( k < n ) {
return f(0.0 + k * (1.0-0.0)/10000.0)*(1.0/10000.0) + sum(k+1,n);
} else { /* k == n の時は、\sum_{i=n}^{n-1} .. → 0 */
return 0.0;
}
}
int main(void) {
s_print_string ( "x^2 を [0,1] 区間で積分すると " );
s_print_double ( sum ( 0, 10000 ) );
s_print_string ( " になります。\n" );
return 0;
}
/*
f(x)=x^2
f(x)=sin(exp(x^2))
*/
- p-006.c (SJIS)
p-006.c
/*
* f(x)=sin(exp(x^2)) を、区間[0,1]で定積分する
*
* 区間 [0,1] を 10000 等分して、短冊を作り、その面積を
* 全て加える
*/
#include <stdio.h>
#include <math.h>
#include "s_print.h"
/*
f(x)=sin(exp(x^2))
*/
double f(double x) {
return sin(exp(x*x));
}
/*
sum ( int k, int n )
\sum_{i=k}^{n-1} S_i
= S_k + \sum_{i=k+1}^{n-1} S_i
= S_k + sum( k+1, n ) 再帰呼出し
*/
double sum ( int k, int n ) {
if ( k < n ) {
return f(0.0 + k * (1.0-0.0)/10000.0)*(1.0/10000.0) + sum(k+1,n);
} else { /* k == n の時は、\sum_{i=n}^{n-1} .. → 0 */
return 0.0;
}
}
int main(void) {
s_print_string ( "sin(exp(x^2)) を [0,1] 区間で積分すると " );
s_print_double ( sum ( 0, 10000 ) );
s_print_string ( " になります。\n" );
return 0;
}
/*
f(x)=x^2
f(x)=
*/
- p-007.c (SJIS)
p-007.c
/*
関数 f(x) が与えられた時に、
f(x_0)=0
となる x_0 を[近似的に..]求める
例
f(x) = a x^2 + b x + c
f(x) = 0 となるのは
x = \frac{-b\pm\sqrt{b^2-4ac}}{2a}
f(x) が 5 次以上の多項式だったら ?
f(x) = \sin{x} - x の時は ?
求め方(条件)
1. 実数解しか考えない
2. f(x) は連続関数
3. 予め、区間[a,b]があたえられていて、
f(a)*f(b)<0
となっている。
-> 区間[a,b] 内に f(x_0)=0 となる x_0 (実数) が含まれる
(中間値の定理)
方針
答えが [a,b] の中にあるので、
m=(a+b)/2 とし
答えが、[a,m] と [m,b] のどちらにあるかを調べる
*/
#include <stdio.h>
#include "s_print.h"
/*
f(x) = x^2 - 2 x - 3 = (x-3)(x+1) -> x = -1, 3
*/
double f( double x ) {
return x * x - 2 * x - 3;
}
/*
f(x_0) = 0 となる x_0 が区間 [a,b] の中にはいっていて
a < b
f(a) < 0 < f(b)
*/
double solve ( double a, double b ) {
if ( b - a < 0.0001 ) {
/* この位精度があれば解とみなそう.. */
return (b+a)/2.0;
} else {
/* まだ、[a,b] は広過ぎるので、幅を狭める必要がある */
if ( f((b+a)/2.0) > 0 ) {
/* 答えは、[a,(b+a)/2.0] の中にある */
return solve ( a, (b+a)/2.0 );
} else {
/* 答えは、[(b+a)/2.0,b] の中にある */
return solve ( (b+a)/2.0, b );
}
}
}
int main(void) {
s_print_string ( "f(x)=x^2-2x-3=0 の解は " );
s_print_double ( solve ( 0.0, 4.0 ) );
s_print_string ( "です。\n" );
return 0;
}
- p-008.c (SJIS)
p-008.c
/*
関数 f(x) が与えられた時に、
f(x_0)=0
となる x_0 を[近似的に..]求める
例
f(x) = x-sin(x)-0.5
f(x) = 0 となるのは
x = \frac{-b\pm\sqrt{b^2-4ac}}{2a}
f(x) が 5 次以上の多項式だったら ?
f(x) = \sin{x} - x の時は ?
求め方(条件)
1. 実数解しか考えない
2. f(x) は連続関数
3. 予め、区間[a,b]があたえられていて、
f(a)*f(b)<0
となっている。
-> 区間[a,b] 内に f(x_0)=0 となる x_0 (実数) が含まれる
(中間値の定理)
方針
答えが [a,b] の中にあるので、
m=(a+b)/2 とし
答えが、[a,m] と [m,b] のどちらにあるかを調べる
*/
#include <stdio.h>
#include <math.h>
#include "s_print.h"
/*
f(x) = x-sin(x)-0.5
*/
double f( double x ) {
return x-sin(x)-0.5;
}
/*
f(x_0) = 0 となる x_0 が区間 [a,b] の中にはいっていて
a < b
f(a) < 0 < f(b)
*/
double solve ( double a, double b ) {
if ( b - a < 0.00000001 ) {
/* この位精度があれば解とみなそう.. */
return (b+a)/2.0;
} else {
/* まだ、[a,b] は広過ぎるので、幅を狭める必要がある */
if ( f((b+a)/2.0) > 0 ) {
/* 答えは、[a,(b+a)/2.0] の中にある */
return solve ( a, (b+a)/2.0 );
} else {
/* 答えは、[(b+a)/2.0,b] の中にある */
return solve ( (b+a)/2.0, b );
}
}
}
int main(void) {
s_print_string ( "f(0.0)=" );
s_print_double ( f(0.0) );
s_print_string ( "\n" );
s_print_string ( "f(PI/2.0)=" );
s_print_double ( f(M_PI/2.0) );
s_print_string ( "\n" );
s_print_string ( "f(x)=x-sin(x)-0.5=0 の解は " );
s_print_double ( solve ( 0.0, M_PI/2.0 ) );
s_print_string ( "です。\n" );
s_print_string ( "f(solve()) の値は " );
s_print_double ( f(solve ( 0.0, M_PI/2.0 )) );
s_print_string ( "です。\n" );
return 0;
}
- p-009.c (SJIS)
p-009.c
/*
* CDATE FILENAME
*
* 二つの整数値をキーボードから入力し、その四則並びに余りを出力する
*/
#include <stdio.h>
#include "s_input.h"
#include "s_print.h"
/*
* print_int_result
*/
void print_int_result ( char *name, int a, int b, char op, int value ) {
/*
print_int_result ( "和", 5, 10, '+', 15 );
->
和 : 5 + 10 = 15
*/
s_print_string ( name ); /* 何を計算したか (和) */
s_print_string ( " : " );
s_print_int ( a ); /* 一つ目の数(5) */
s_print_char ( op ); /* 演算子(+) */
s_print_int ( b ); /* 二つ目の数(10) */
s_print_char ( '=' ); /* 等号(=) */
s_print_int ( value ); /* 結果(15) */
s_print_newline();
}
/*
* print_int_calc
*/
void print_int_calc ( int a, int b ) {
print_int_result ( "和", a, b, '+', a + b ); /*和*/
print_int_result ( "差", a, b, '-', a - b ); /*差*/
print_int_result ( "積", a, b, '*', a * b ); /*積*/
/* ここは自分で */ /*商*/
print_int_result ( "余り", a, b, '%', a % b ); /*余り*/
}
/*
* print_int_calc_1
*/
void print_int_calc_1 ( int a ) {
print_int_calc ( a, s_input_int() );
}
/*
* main
*/
int main( int argc, char *argv[] )
{
print_int_calc_1 ( s_input_int() );
/*
print_int_calc ( s_input_int(), s_input_int() );
の時、キーボードから 5, 10 といれる
後ろが 5, 前が 10 になります
print_int_calc ( 10, 5 ) となる
*/
return 0;
}
- p-010.c (SJIS)
p-010.c
/*
* CDATE FILENAME
*
* 二つの浮動小数点数値をキーボードから入力し、その四則を出力する
* 課題 01 の int を double 変更するだけ
*/
#include <stdio.h>
#include "s_input.h"
#include "s_print.h"
/*
* print_double_result
*/
void print_double_result ( char *name, double a, double b, char op, double \
value ) {
s_print_string ( name );
s_print_string ( " : " );
s_print_double ( a );
s_print_char ( op ); /* 演算子(+) */
s_print_double ( b ); /* 二つ目の数(10) */
s_print_char ( '=' );
s_print_double ( value );
s_print_newline();
}
/*
* print_double_calc
*/
void print_double_calc ( double a, double b ) {
print_double_result ( "和", a, b, '+', a + b );
print_double_result ( "差", a, b, '-', a - b );
print_double_result ( "積", a, b, '*', a * b );/*積*/
/* ここは自分で */ /*商*/
/* 浮動小数点数の場合は「余り」の演算はない */
/* 10.0 % 3.0 とは「エラー」になる */
}
/*
* print_double_calc_1
*/
void print_double_calc_1 ( double a ) {
print_double_calc ( a, s_input_double() );
}
/*
* main
*/
int main( double argc, char *argv[] )
{
print_double_calc_1 ( s_input_double() );
return 0;
}
- memo.txt (SJIS)
memo.txt
C 言語で、浮動小数点数型 ( double ) が使えるようになった
C 言語で、誤差付きだが、実数計算ができるようになった
解析系 ( 微分、積分、確率等.. ) の計算ができる
数値の計算しかできない
「積分」といっても、原始関数が得られるわけではけではない
常に、誤差を含む
計算機が、「有限」しか扱えないので
「数学」では、「無限」が扱える
「数学」では、「できる」か「できない」かの何方か
数学で「解ける」という場合は「等号が成立」する
問題が難しくなっている
「解けない」場合が増える
「計算機」は、「近付ける」事ができる(等しくはならない)
計算機で「解ける」は「近似値」が得られる
「答え」要求される条件が弱いので、
-> 数学で「解け」ない問題が「解ける」
数値積分
I = \int_a^b f(x) dx の近似値を求める
リーマンの公式より
\int_a^b f(x) dx
= \lim_{n\rightarrow\infty}
\frac{b-a}{n}\sum_{i=0}^{n-1} f(a+i\frac{b-a}{n})
なので、n を適当な大きな数 ( 1000 とか.. 必要なだけ大きく )
で、I の近似値とする。