見出し画像

プログラミング学習の記録 #014(C)

卒業研究に取り組んでいたため、プログラミング学習の進捗が停滞していた。卒業研究における数値計算では、プログラミング技術的な問題は、今のところ発生していないが、それほど難解でないながらも内容が複雑で時間を要している。ただ、パラメータ化モデルの数値計算を行ううえで、計算機による繰り返し計算が抜群の力を発揮している。うまく利用できると、プログラミングもおもしろいかもしれない、と思えるようになった。

前回の復習

練習問題 10.2

2個の整数を小さい順に並べ替える関数を作成せよ。

#include <stdio.h>

void change(int *p1, int *p2)
{
    int a ;

    if(*p1 > *p2)
    {
        a = *p1 ;
        *p1 = *p2 ;
        *p2 = a ;
    }

    return ;
}

int main()
{
    int x,y ;

    printf("Input integer 1: ");
    scanf("%d",&x);
    printf("Input integer 2: ");
    scanf("%d",&y);
    
    printf("%d,%d\n",x,y);
    change(&x,&y) ;
    printf("%d,%d\n",x,y);

    printf("HAPPY SMILE (^_^)v\n");
    return 0;
}

練習問題 10.3(二分法)

二分法により、非線形方程式を解くプログラムを作成し、これを用いて、

$$
\begin{matrix}
f(x) =& x^{2} - a \\
f(x) =& x^{3} - a \\
f(x) =& \sin x - a
\end{matrix}
$$

($${a}$$は定数)などの関数について解を求めてみよ。

#include <stdio.h>
#include <math.h>

#define function_name pow(x,3)-12       //Input function.
#define start_x1 3                      //Input start point.
#define delta_delta 0.03                //Input stride for searching first status.
#define range 0.0001                    //Input error range of solution.

double func(double x)
{
    double f ;
    f = function_name ;
    return f ;
}

void change(double *p1, double *p2)
{
    double a ;

    if(*p1 > *p2)
    {
        a = *p1 ;
        *p1 = *p2 ;
        *p2 = a ;
    }

    return ;
}

int main()
{
    double x1, x2 ;
    double f1, f2 ;
    double delta ;
    int j ;

    x1 = start_x1 ;
    x2 = x1 ;
    f1 = func(x1) ;
    f2 = func(x2) ;
    delta = 0 ;
    j = 1 ;

    while(f1 * f2 > 0)
    {
        x2 = x2 + delta * j ;
        f1 = func(x1) ;
        f2 = func(x2) ;
        delta = delta + delta_delta ;
        j = j * (-1) ;
    }

    change(&x1,&x2) ;

    printf("First status\n");
    printf("x1 = %7.4f, x2 = %7.4f\n",x1,x2);
    printf("-----\n");


    double x3, f3 ;

    while(fabs(x1 - x2) > range)
    {
        x3 = ( x1 + x2 ) / 2 ;
        f3 = func(x3) ;
        if(fabs(f3) < range)
        {
            x1 = x3 ;
            x2 = x3 ;
        }else if(f3 > 0)
        {
            x2 = x3 ;
        }else
        {
            x1 = x3 ;
        }
    }

    f1 = func(x1) ;
    f2 = func(x2) ;

    printf("Solution:\n");
    printf("%9.5f < x <%9.5f\n",x1,x2);

    printf("HAPPY SMILE (^_^)v\n");
    return 0;
}

このコードでは、$${f(x) = x^{3} - 12}$$の解を求めている。

構造体

データ処理を行うときには、1つのデータが複数の要素を含んでいることがある。このようなときに、既存のデータ型を組み合わせた複合的なデータ型が利用できると便利である。構造体によって、それを実現することができる。教科書を参考にして、複素数の積を計算するコードを書いた。

#include <stdio.h>
#include <math.h>
#include <stdlib.h>

struct dcomp
{
    double Re, Im ;
};

int main()
{
    struct dcomp x, y, z ;

    x.Re = 2.0 ;
    x.Im = 3.0 ;
    y.Re = 1.0 ;
    y.Im = 2.0 ;

    z.Re = x.Re * y.Re - x.Im * y.Im ;
    z.Im = x.Re * y.Im - x.Im * y.Re ;

    printf("(%4.1f + %4.1fi) * (%4.1f + %4.1fi) = %4.1f + %4.1fi\n",x.Re,x.Im,y.Re,y.Im,z.Re,z.Im);

    printf("HAPPY SMILE (^_^)v\n");
    return 0;
}

構造体でポインタを用いる際は、以下のように宣言すればよい。

struct dcomp
{
    double x,y ;
};

int main()
{
    struct dcomp *p1 ;

    return 0;
}

次に、3次元空間内の2点を入力し、その2点間の距離を求めるプログラムコードを書いた。

#include <stdio.h>
#include <math.h>

typedef struct point3D
{
    double x,y,z;
} point3D;

void readpoint(point3D *p)
{
    printf("Input the coordinates (x y z): ");
    scanf("%lf %lf %lf",&(*p).x,&(*p).y,&(*p).z);
}

double distance(point3D r1, point3D r2)
{
    double dis;

    dis = pow(r1.x - r2.x, 2) + pow(r1.y - r2.y, 2) + pow(r1.z - r2.z, 2) ;    
    dis = sqrt(dis) ;

    return dis ;
}

int main()
{
    point3D r1,r2;
    double dis;

    printf("Point 1\n");
    readpoint(&r1);
    printf("Point 2\n");
    readpoint(&r2);

    dis = distance(r1,r2);

    printf("The distance between point 1 and 2 = %.2f\n",dis);

    printf("HAPPY SMILE (^_^)v\n");
    return 0;
}

構造体では、配列を用いることもできる。複数の質点が存在するときに、それらの質点の重心を位置を求めるプログラムコードを書いた。重心$${\bm{x}_{\mathrm{center}}}$$は、以下のような計算により求めることができる。

$$
\bm{x}_{\mathrm{center}}
= \dfrac{\sum m_{i} \bm{x_{i}}}{\sum m_{i}}
$$

#include <stdio.h>
#include <stdlib.h>
#define number 3

typedef struct mass_point
{
    double m,x,y,z;
} mp;

void readpoint(mp *p)
{
    printf("Input the mass: ");
    scanf("%lf",&(*p).m);
    if((*p).m < 0)
    {
        exit(1);
    }
    printf("Input the coordinates (x y z): ");
    scanf("%lf %lf %lf",&(*p).x,&(*p).y,&(*p).z);
}

mp center(mp r[])
{
    mp rc;
    int i;

    rc.m = 0;
    rc.x = 0;
    rc.y = 0;
    rc.z = 0;
    for( i = 0 ; i < number ; i = i + 1 )
    {
        rc.m = rc.m + r[i].m ;
        rc.x = rc.x + r[i].x * r[i].m ;
        rc.y = rc.y + r[i].y * r[i].m ;
        rc.z = rc.z + r[i].z * r[i].m ;
    }
    rc.x = rc.x / rc.m ;
    rc.y = rc.y / rc.m ;
    rc.z = rc.z / rc.m ;

    return rc;
}

int main()
{
    mp r[number];
    mp rc;
    int i;

    for( i = 0 ; i < number ; i = i + 1 )
    {
        printf("Point %d\n",i+1);
        readpoint( &(r[i]) );
    }
    
    rc = center(r) ;

    printf("Sum of mass = %7.2f\n",rc.m);
    printf("Center of mass = (%7.2f,%7.2f,%7.2f)\n",rc.x,rc.y,rc.z);

    printf("HAPPY SMILE (^_^)v\n");
    return 0;
}

構造体配列は、N体シミュレーションなどで利用できそうである。

共用体

共用体変数のメンバのうち、最も多くの記憶領域を必要とするメンバの分だけの領域が確保される。そのため、何らかの事情によってデータ型が混在したデータを扱う必要があって、記憶領域を節約したい場合に有用である場合がある。エラーや欠損値を含むデータを扱う場合に用いるとよい。今後、使うことがないだろうと思ったので、このサイトこのサイトを見るだけにした。

-----

動け!タイムライン

この記事が参加している募集

動物園か水族館にいきたいですね。