投稿者「admin」のアーカイブ

ファイルのタイムスタンプの変更

指定したファイルのタイムスタンプを変更する方法について説明します.
 
UNIX ではファイルの時間に関する情報には次の3つのものがあります.
1) 最終アクセス時刻: atime
2) 最終更新時刻  : mtime
3) 最終属性変更時刻: ctime
 
この内 atime と mtime を,関数 utime を使って変更することができます.
 
utime を実行するに先立って,atime, mtime の値を utimbuf 構造体に格納しておく必要があります.
この構造体の内容に従って,指定したファイルのタイムスタンプを変更します.
 
utimbuf 構造体の定義

struct utimbuf {
	time_t actime;	/* atime : access time */
	time_t modtime;	/* mtime : modification time */
};

 
char *fname で示されるパスのファイルのタイムスタンプを struct utimbuf utb の内容にする

utime(fname,&utb)

処理が正常に終了すると戻り値は0となる.
 
サンプルプログラム s_utime.c:ファイル s_utime.out のタイムスタンプを1年後に設定する

#include	
#include	
#include	
#include	

int main()
{
	FILE	*f;
	time_t	t;
	char	ftime[128], fname[128];;
	struct	tm	*tstamp;
	struct	utimbuf	utb;

	/* file generation */
	sprintf(fname,"s_utime.out");
	f = fopen(fname,"w");
	fclose(f);

	/* setting 1 year later */
	t = time(NULL) + 86400 * 365;
	tstamp = gmtime(&t);

	strftime(ftime,sizeof(ftime),"%Y/%m/%d(%a) %H:%M:%S",tstamp);
	printf("%s\n",ftime);

	utb.actime = t;
	utb.modtime = t;

	/* changing time stamp */
	if ( utime(fname,&utb) != 0 ) {
		fprintf(stderr,"utime failure!\n");
	}
}

実行例

$ date			← 現在の日付を調べる
2015年 3月28日 土曜日 18時11分16秒 JST
$ s_utime		← 1年後の日付にする
2016/03/27(Sun) 09:11:24

この後 “ls -la” コマンドで s_utime.out のタイムスタンプを調べる

-rwxr-xr-x    1 user1  staff    9056  3 28 17:57 s_utime
-rw-r--r--    1 user1  staff     585  3 28 17:57 s_utime.c
-rw-r--r--    1 user1  staff       0  3 27  2016 s_utime.out

ディレクトリを開く

ディレクトリの配下には,いくつかのファイルやサブディレクトリが配置されています.
 
ここでは,ディレクトリに登録されているそれらの項目の名前を取得する方法について説明します.
 
1. ディレクトリを開く
 指定した名前のディレクトリを開くには opendir 関数を呼び出します.
この関数はディレクトリに関する情報を収めた DIR 構造体へのポインタを戻り値として返します.
処理が失敗すると NULL を返します.
 
ディレクトリを開いた後は,そのポインタが指し示す構造体のメンバにアクセスすることでディレクトリに関する情報を取得することができます.
 
例 char *path に与えられたディレクトリを開く

DIR	*dr;
dr = opendir(path);

 
2. ディレクトリ配下の項目を取得する
 readdir 関数を呼び出すことで開いたディレクトリの配下の項目を1つづつ取得することができます.
この関数は,項目の情報を格納する dirent 構造体へのポインタを戻り値として返します.
(項目を全部取得してしまった後は戻り値は NULL となります)
 
例 dr として開いたディレクトリから項目を取得する

struct	dirent	*de;
de=readdir(dr)

 
dirent 構造体の定義

struct dirent {
    ino_t          d_ino;       /* inode 番号 */
    off_t          d_off;
    unsigned short d_reclen;    /* このレコードの長さ */
    unsigned char  d_type;      /* ファイル種別 */
    char           d_name[256]; /* ファイル名 */
};

de->d_name を参照することで項目のファイル名を取得できる.
 
3. ディレクトリを閉じる
 ディレクトリへのアクセスが終われば,閉じる必要があります.
開いたディレクトリを閉じるには関数 closedir を呼び出します.
 
例 dr として開いたディレクトリを閉じる

closedir(dr);

 
サンプルプログラム: 指定したディレクトリ配下の項目を全てリストアップする

#include	
#include	
#include	

int main(ac,av)
int  ac;
char **av;
{
	char	*path;
	DIR	*dr;
	struct	dirent	*de;
	int	i = 0;

	path = av[1];
	dr = opendir(path);
	if ( dr == NULL ) {
		fprintf(stderr,"Can not open directory: %s\n",path);
		return(-1);
	}

	while ( -1 ) {
		if ( (de=readdir(dr)) == NULL ) {
			break;
		}
		i++;
		printf("item %03d: %s\n",i,de->d_name);
	}

	closedir(dr);
}

 
実行例: 上のサンプルを s_opendir.c として作って実行する.
プログラム本体が次のようなディレクトリにあるものとする.

$ ls -la
total 1200
drwxr-xr-x   16 user1  staff     544  3 27 19:47 .
drwxr-xr-x+ 166 user1  staff    5644  2 28 15:04 ..
-rw-------    1 user1  staff   12288  3 27 19:47 .s_opendir.c.swp
-rwxr-xr-x    1 user1  staff     369  6  1  2014 cmd1
-rw-r--r--    1 user1  staff     360  6  1  2014 inp
-rwxr-xr-x    1 user1  staff    8936  3 15 16:55 s_fstat
-rw-r-----    1 user1  staff    1488  3 15 16:55 s_fstat.c
-rwxr-xr-x    1 user1  staff    8780  3 27 19:47 s_opendir
-rw-r--r--    1 user1  staff     423  3 27 19:47 s_opendir.c
-rwxr-xr-x    1 user1  staff    8688  3 16 19:29 s_time
-rw-r--r--    1 user1  staff     450  3 16 19:29 s_time.c
-rwxr-xr-x    1 user1  staff    8568  3 15 21:49 s_timeb
-rw-r--r--    1 user1  staff     333  3 16 20:08 s_timeb.c
lrwxr-xr-x    1 user1  staff       9  3 15 16:22 sl -> s_fstat.c
-rw-r--r--@   1 user1  staff  258640  3 15 16:26 sl2
-rw-r--r--@   1 user1  staff  258640  3 15 20:57 sl3

ここでプログラムを実行して,このディレクトリ自身 “.” の中身をリストアップする.

$ s_opendir .
item 001: .
item 002: ..
item 003: .s_opendir.c.swp
item 004: cmd1
item 005: inp
item 006: s_fstat
item 007: s_fstat.c
item 008: s_opendir
item 009: s_opendir.c
item 010: s_time
item 011: s_time.c
item 012: s_timeb
item 013: s_timeb.c
item 014: sl
item 015: sl2
item 016: sl3

ファイルの属性の取得

ファイルシステムにはファイルディレクトリリンクといった異なる種類の実体があります.また,それらにはアクセスされた時刻の情報も属性として記録されています.
 
ここでは,指定したパスの実体の属性を調べる方法について説明します.
 
指定したパスの属性を取得するには stat という関数を呼び出します.
また,stat の呼び出しで得られた属性の情報は stat 構造体に格納されます.
 
例.ポインタ cahr *path によって示されるパス名の文字列があるとき,そのパスの属性を得る方法

struct	stat	buf;
r = stat(path,&buf);

(int r は戻り値で,stat の処理が正常に終了した場合は 0 となる)
これにより,構造体 buf にパスの各種の属性が格納される.
 
指定したパスがシンボリックリンクである場合,そのリンク先の実体の属性を求めるのか,あるいはリンクそのものの属性を求めるかは全く意味が異なります.
「リンクであるかどうか」の情報が必要な場合は stat ではなく lstat を用います.
 
構造体 stat の定義

struct stat {
	dev_t     st_dev;     /* ファイルがあるデバイスの ID */
	ino_t     st_ino;     /* inode 番号 */
	mode_t    st_mode;    /* アクセス保護 */
	nlink_t   st_nlink;   /* ハードリンクの数 */
	uid_t     st_uid;     /* 所有者のユーザー ID */
	gid_t     st_gid;     /* 所有者のグループ ID */
	dev_t     st_rdev;    /* デバイス ID (特殊ファイルの場合) */
	off_t     st_size;    /* 全体のサイズ (バイト単位) */
	blksize_t st_blksize; /* ファイルシステム I/O での
					ブロックサイズ */
	blkcnt_t  st_blocks;  /* 割り当てられた 512B のブロック数 */
	struct timespec st_atim;  /* 最終アクセス時刻 */
	struct timespec st_mtim;  /* 最終修正時刻 */
	struct timespec st_ctim;  /* 最終状態変更時刻 */
};
#define st_atime st_atim.tv_sec
#define st_mtime st_mtim.tv_sec
#define st_ctime st_ctim.tv_sec

 
この構造体のメンバにファイルに関する各種の情報が格納されています.
特に st_mode には,それがファイルなのかディレクトリなのか,
あるいはシンボリックリンクなのかという情報が格納されており,
実体の種別を識別するのに使うことができます.
 
ファイル/ディレクトリ/シンボリックリンクの判別
 st_mode から種別を判定する下記のような関数があります.
S_ISREG : 通常のファイルであることを判定
S_ISDIR : ディレクトリであることを判定
S_ISLNK : シンボリックリンクであることを判定
 
サンプルプログラム : 指定したパスの情報を表示するプログラム

#include	
#include	
#include	
#include	
#include	

struct	stat	buf;
struct	tm	*ts;

int main(ac,av)
int	ac;
char	**av;
{
	int	r, size, mode;
	char	*path, tf[128];

	if ( ac < 2 ) {
		fprintf(stderr,"No arguments.\n");
		return(-1);
	}

	path = av[1];	// パス名を取得
	fprintf(stderr,"path: %s\n",path);

//	r = stat(path,&buf);	// パスの属性を取得
	r = lstat(path,&buf);	// パスの属性を取得
	if ( r != 0 ) {		// エラー処理
		fprintf(stderr,"error: stat = %d\n",r);
		return(-1);
	}

//	ts = localtime(&(buf.st_atime));	// 最終アクセス時刻を取得
	ts = gmtime(&(buf.st_atime));		// 最終アクセス時刻を取得
//	strftime(tf,sizeof(tf),"%Y/%m/%d(%a) %H:%M:%S(%z)",ts);
	strftime(tf,sizeof(tf),"%Y/%m/%d(%a) %H:%M:%S",ts);
	printf("Last access(st_atime)       = %s\n",tf);	// 表示

//	ts = localtime(&(buf.st_mtime));	// 最終修正時刻を取得
	ts = gmtime(&(buf.st_mtime));		// 最終修正時刻を取得
//	strftime(tf,sizeof(tf),"%Y/%m/%d(%a) %H:%M:%S(%z)",ts);
	strftime(tf,sizeof(tf),"%Y/%m/%d(%a) %H:%M:%S",ts);
	printf("Last modified(st_mtime)     = %s\n",tf);	// 表示

//	ts = localtime(&(buf.st_ctime));	// 最終状態変更時刻を取得
	ts = gmtime(&(buf.st_ctime));		// 最終状態変更時刻を取得
//	strftime(tf,sizeof(tf),"%Y/%m/%d(%a) %H:%M:%S(%z)",ts);
	strftime(tf,sizeof(tf),"%Y/%m/%d(%a) %H:%M:%S",ts);
	printf("Last state change(st_ctime) = %s\n",tf);	// 表示

	size = (int)(buf.st_size);	// サイズを取得
	printf("size: %d (bytes)\n",size);	// 表示

	mode = (int)(buf.st_mode);	// アクセス属性の取得
	printf("mode: %o\n",mode);	// 表示

	// ファイル/ディレクトリ/シンボリックリンクの判定
	printf("type: /");
	if ( S_ISREG(buf.st_mode) ) {
		printf("regular file/");
	}
	if ( S_ISDIR(buf.st_mode) ) {
		printf("directory/");
	}
	if ( S_ISLNK(buf.st_mode) ) {
		printf("simlink/");
	}
	printf("\n");
}

このプログラムを s_fstat という名前で作成して実行した例を次に示します.
 
実行例1 ディクレイトリ "." の属性を調べる例

$ s_fstat .
path: .
Last access(st_atime)       = 2015/03/27(Fri) 10:28:37
Last modified(st_mtime)     = 2015/03/16(Mon) 11:08:31
Last state change(st_ctime) = 2015/03/16(Mon) 11:08:31
size: 442 (bytes)
mode: 40755
type: /directory/
$

 
実行例2 ソースファイル "s_fstat.c" の属性を調べる例

$ s_fstat s_fstat.c
path: s_fstat.c
Last access(st_atime)       = 2015/03/23(Mon) 10:15:09
Last modified(st_mtime)     = 2015/03/15(Sun) 07:55:09
Last state change(st_ctime) = 2015/03/15(Sun) 07:55:09
size: 1488 (bytes)
mode: 100640
type: /regular file/
$

 
実行例3 シンボリックリンク "sl" の属性を調べる例

$ s_fstat sl
path: sl
Last access(st_atime)       = 2015/03/15(Sun) 07:22:56
Last modified(st_mtime)     = 2015/03/15(Sun) 07:22:56
Last state change(st_ctime) = 2015/03/15(Sun) 07:22:56
size: 9 (bytes)
mode: 120755
type: /simlink/
$

時刻の扱い(1)

 UNIX系システムの時刻情報の考え方はとても単純です.
それはどのようなものかというと,
 
「”西暦1970年1月1日0時0分0秒”を基準として,その後の秒数で時刻を表現する」
 
というものです.そして各種の関数を呼び出すことで,
秒数で表現された時刻情報から,
年,月,日,曜日,時,分,秒などの情報を取得することになります.
 
また,日付や時,分,秒の値を保持するための各種の構造体も
提供されています.
 
■ システムの現在時刻の取得(秒単位)
 OSの現在時刻(秒単位)を取得するには time 関数を使います.
 
例.

time_t    t;
t = time(NULL);

上の例のようにすると,t の中に現在時刻が秒数として得られます.
 
日付や時分秒の情報を格納する構造体として tm があり,
localtime 関数や gmtime 関数を使用することで
time_t 型のデータから tm の各メンバに情報を与えることができます.
 
例.

time_t    t;
struct tm *jst;
t = time(NULL);
jst = localtime(&t);

上の例のようにすることで,t の値から日付や時分秒の数値を算出して
それを jst の各メンバに格納します.
localtime 関数はOSのタイムゾーンに合った形で日付と時刻を取得します.
また類似の関数に gmtime というものがあり,これを用いると
グリニッジ標準時の形式で日付と時刻を取得することができます.
 
ちなみに,構造体 tm の中身(定義)は下記のようなものです.

struct tm {
	int tm_sec;        /* 秒 (0-60) */
	int tm_min;        /* 分 (0-59) */
	int tm_hour;       /* 時間 (0-23) */
	int tm_mday;       /* 月内の日付 (1-31) */
	int tm_mon;        /* 月 (0-11) */
	int tm_year;       /* 年 - 1900 */
	int tm_wday;       /* 曜日 (0-6, 日曜 = 0) */
	int tm_yday;       /* 年内通算日 (0-365, 1 月 1 日 = 0) */
	int tm_isdst;      /* 夏時間 */
};

この後,jst->tm_year を参照することで,西暦年(下2桁)の数値を得ることができます.
 
便利な関数として strftime というものがあり,これを使用することで,
日付や時刻を表現する文字列を得ることができます.
例.現在の日付と時刻を1秒感覚で表示するプログラム

#include	
#include	

int main()
{
	time_t	t;
	struct	tm	*gmt, *jst;
	int	s1, s2;
	char	fgmt[128], fjst[128];

	s2 = 0;
	while ( -1 ) {
//		t = time(NULL);
		time(&t);
		gmt = gmtime( &t );
		jst = localtime( &t );
		s1 = gmt->tm_sec;
		if ( s1 != s2 ) {
			strftime(fgmt,sizeof(fgmt),"%Y/%m/%d(%a) %H:%M:%S",gmt);
			strftime(fjst,sizeof(fjst),"%Y/%m/%d(%a) %H:%M:%S(%a)",jst);
			printf("%s [%s]\n",fgmt,fjst);
			s2 = s1;
		}
	}
}

実行結果の例.

$ s_time
2015/03/16(Mon) 10:56:34 [2015/03/16(Mon) 19:56:34(Mon)]
2015/03/16(Mon) 10:56:35 [2015/03/16(Mon) 19:56:35(Mon)]
2015/03/16(Mon) 10:56:36 [2015/03/16(Mon) 19:56:36(Mon)]
2015/03/16(Mon) 10:56:37 [2015/03/16(Mon) 19:56:37(Mon)]
2015/03/16(Mon) 10:56:38 [2015/03/16(Mon) 19:56:38(Mon)]
2015/03/16(Mon) 10:56:39 [2015/03/16(Mon) 19:56:39(Mon)]
^C
$

 
■ システムの現在時刻の取得(ミリ秒単位)
 OSの現在時刻(ミリ秒単位)を取得するには ftime 関数を使います.
この関数を使用すると,秒とミリ秒の情報が構造体 timeb のメンバに格納されます.
 
例.10分の1秒毎に時刻の秒数を表示するプログラム

#include	
#include	

struct	timeb	tb;

int main()
{
	int	sec,sec2, msec,msec2;

	ftime( &tb );
	sec2 = tb.time;
	msec2 = tb.millitm / 100;
	while ( -1 ) {
		ftime( &tb );
		sec = tb.time;
		msec = tb.millitm / 100;
		if ( msec != msec2 ) {
			printf("%d.%d\n",sec,msec);
			sec2 = sec;
			msec2 = msec;
		}
	}
}

 
localtime の逆関数
 tm 構造体の内容から,その時刻に対応する time_t の値を求めるには mktime 関数を使います.
 
例1.localtime で変換した tm 構造体の内容を time_t に逆変換する

#include	
#include	

int main()
{
	time_t	t;
	struct	tm	*jst;
	char	fjst[128];

//	t = time(NULL);
	time(&t);
	printf("Now, time_t is %ld\n",t);

	jst = localtime( &t );
	strftime(fjst,sizeof(fjst),"%Y/%m/%d(%a) %H:%M:%S(%a)",jst);
	printf("%s\n",fjst);

	t = mktime( jst );
	printf("mktime is      %ld\n",t);
}

実行例

$ s_mktime
Now, time_t is 1427529755
2015/03/28(Sat) 17:02:35(Sat)
mktime is      1427529755

 
例2.コマンドラインから入力した日付と時刻から time_t を求める

#include	
#include	

int main(ac,av)
int	ac;
char	**av;
{
	int	year, month, day, hour, min, sec;
	time_t	t;
	struct	tm	jst, *jst2;
	char	fjst[128];

	sscanf(av[1],"%d",&year);
	sscanf(av[2],"%d",&month);
	sscanf(av[3],"%d",&day);
	sscanf(av[4],"%d",&hour);
	sscanf(av[5],"%d",&min);
	sscanf(av[6],"%d",&sec);
	year  -= 1900;
	month -= 1;

	jst.tm_year   = year;
	jst.tm_mon    = month;
	jst.tm_mday   = day;
	jst.tm_hour   = hour;
	jst.tm_min    = min;
	jst.tm_sec    = sec;
	jst.tm_isdst  = -1;

	t = mktime(&jst);
	printf("%04d/%02d/%02d %02d:%02d:%02d\n",
			year+1900,month+1,day,hour,min,sec);
	printf("time_t is %ld\n",t);

	jst2 = localtime( &t );
	strftime(fjst,sizeof(fjst),"%Y/%m/%d(%a) %H:%M:%S",jst2);
	printf("%s\n",fjst);

	t = mktime( jst2 );
	printf("mktime is %ld\n",t);
}

実行結果の例

$ s_mktime2 2015 3 29 13 16 00
2015/03/29 13:16:00
time_t is 1427602560
2015/03/29(Sun) 13:16:00
mktime is 1427602560

アプリケーションプログラムを作るには

プログラミング言語の最終的な目的は,アプリケーションプログラムの作成です.
いわゆる「アプリ」を作るのが目的です.
 
ここではJavaで実現するアプリにはどのような形があるのかを紹介します.

● コマンドとしてアプリを作る

 Windowsのコマンドプロンプトウィンドウ(Macの場合はターミナルウィンドウ)で実行するプログラムで,基本的にはグラフィックスは扱いません.これの実現は最も手軽で,標準入力(System.inなど)からユーザの操作を受付,標準出力(System.outなど)に対してメッセージを表示するスタイルです.

● アプレットを作る

 Webブラウザ上で実行するプログラムで,HTMLコンテンツの中に埋め込んで使います.

● GUIアプリを作る (1) : Swingの利用
● GUIアプリを作る (2) : SWTの利用
● GUIアプリを作る (3) : FXの利用

応用作品

 GMPもMPFRもとても有用なライブラリですが,使い方に関して言うと「ちょっと煩わしい」感じがします.そこで,当ゼミではこれらライブラリをちょっと使いやすくするための一種の「ラッパー」みたいなものをC++言語で記述して使っています.
 
これはC++で高精度演算をするための関数群を提供するヘッダファイル “bignum.h” として実装したもの(下記)です.

作品:bignum.h
 まだまだツッコミどころのあるコードですが,計算が便利になっています.(^^)
 
【bignum.hの使い方】
 bignum.hは高精度演算のための2つのクラス(下記)を提供します.
 
1) BigQ : 計算精度を落とさずに算術演算(加減乗除)を行うためのクラス
2) BigF : 指定した精度(ビット長)で算術演算と各種関数の計算を行うためのクラス
 
基本的な使い方を例を挙げて説明します.

Step-1: オブジェクトの宣言
例: BigF pi(332), c3(332), x(332), y(332);
 これで332ビット(10進数で約100桁)の精度を持つ4つの変数(オブジェクト)pi,c3,x,yが生成されます.
 
Step-2: 値の設定
例: c3 = 3;
 これでc3に3が代入されます.オブジェクトを宣言する時に値を代入することもできます.
 (例えば,BigF c3(3,332); )
 
Step-3: 計算の実行
例: pi.setPi();
 これでpiに円周率が代入されます.
 
Step-4: 値の出力
例: pi.toString(s);
   printf(“pi: %s\n\n”,s);
 これでpiの内容が文字列としsに格納されます.
 
プログラム例: π,cos(π),π/3,cos(π/3)を求めるプログラム

#include	
#include	"bignum.h"

int main()
{
	char	*s;
	s = (char*)malloc(1048576);

	BigF	pi(332), c3(332), x(332), y(332);

	c3 = 3;

	pi.setPi();
	pi.toString(s);
	printf("pi: %s\n\n",s);

	y.setCos(pi);
	y.toString(s);
	printf("y=cos(pi): %s\n\n",s);

	x.setDiv(pi,c3);
	x.toString(s);
	printf("pi/3: %s\n\n",s);

	y.setCos(x);
	y.toString(s);
	printf("y=cos(pi/3): %s\n",s);
}

実行結果

pi: 3.1415926535897932384626433832795028841971693993751058209749445923078164062862089986280348253421170678

y=cos(pi): -1.0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000

pi/3: 1.0471975511965977461542144610931676280657231331250352736583148641026054687620696662093449417807056892

y=cos(pi/3): 0.50000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000011

※ 末の桁の誤差に注意してください.
 
=== 簡易リファレンス ===

【有理数クラス:BigQ】
■ オブジェクトの生成
BigQ x 初期値なし
BigQ x(値) 生成時に初期値(値)を設定する.
■ オブジェクトの廃棄
x.Free() BigQ型のオブジェクトxを廃棄する.
■ C言語の基本的な値の代入
x = 値 BigQ型のオブジェクトxに値を代入する.
■ C言語の変数への変換
x.toInt() BigQ型のオブジェクトxをint型の値に変換したものを返す.
x.toLong() BigQ型のオブジェクトxをlong型の値に変換したものを返す.
x.toDouble() BigQ型のオブジェクトxをdouble型の値に変換したものを返す.
x.toString(s) BigQ型のオブジェクトxを文字列(char *s)に変換する.
■ 演算
x.setAdd(v1,v2) v1+v2(共にBigQ型のオブジェクト)の値をxに代入する.
x.setSub(v1,v2) v1-v2(共にBigQ型のオブジェクト)の値をxに代入する.
x.setMul(v1,v2) v1*v2(共にBigQ型のオブジェクト)の値をxに代入する.
x.setDiv(v1,v2) v1/v2(共にBigQ型のオブジェクト)の値をxに代入する.
x.setAdd(v) BigQ型のオブジェクトxにBigQ型のオブジェクトvの値を加算する.(計算結果はxの値になる)
x.setSub(v) BigQ型のオブジェクトxからBigQ型のオブジェクトvの値を引く.(計算結果はxの値になる)
x.setMul(v) BigQ型のオブジェクトxにBigQ型のオブジェクトvの値を掛ける.(計算結果はxの値になる)
x.setDiv(v) BigQ型のオブジェクトxをBigQ型のオブジェクトvの値で割る.(計算結果はxの値になる)
x.setNeg(v) BigQ型のオブジェクトvの符号を反転した値をxに代入する.
x.setInv(v) BigQ型のオブジェクトvの逆数をxに代入する.
x.setPow(v,p) BigQ型のオブジェクトvのp乗をxに代入する.(unsigned long p)
x.setInc() xの値を1増やす.
x.setDec() xの値を1減らす.
x.setFact(n) nの階乗をxに代入する.(unsigned long n)
■ 述語(比較など)
x == y BigQ型のオブジェクトx,yの値が等しければtrue,それ以外はfalseを返す.
x != y BigQ型のオブジェクトx,yの値が異なればtrue,それ以外はfalseを返す.
x > y BigQ型のオブジェクトx,yの値を比較し,x>yならばtrue,それ以外はfalseを返す.
x < y BigQ型のオブジェクトx,yの値を比較し,x
x >= y BigQ型のオブジェクトx,yの値を比較し,x>=yならばtrue,それ以外はfalseを返す.
x <= y BigQ型のオブジェクトx,yの値を比較し,x<=yならばtrue,それ以外はfalseを返す.

 

【浮動小数点数クラス:BigF】
■ オブジェクトの生成
BigF x デフォルト精度で生成する.
BigF x(精度) 生成時に精度(ビット長)を設定する.
BigF x(値,精度) 生成時に初期値(値)と精度(ビット長)を設定する.
■ オブジェクトの精度の変更
x.setPrec(精度) BigF型オブジェクトxの精度(ビット長)を変更(再設定)する.
■ オブジェクトの廃棄
x.Free() BigF型のオブジェクトxを廃棄する.
■ C言語の基本的な値の代入
x = 値 BigF型のオブジェクトxに値を代入する.
■ C言語の変数への変換
x.toInt() BigF型のオブジェクトxをint型の値に変換したものを返す.
x.toLong() BigF型のオブジェクトxをlong型の値に変換したものを返す.
x.toDouble() BigF型のオブジェクトxをdouble型の値に変換したものを返す.
x.toString(s) BigF型のオブジェクトxを文字列(char *s)に変換する.
■ C言語の基本的な値の代入
x = 値 BigF型のオブジェクトxに値を代入する.
■ 特殊な値の代入
x.setZero(符号) BigF型のオブジェクトxに0を代入する.符号はint型で,正なら+0を,負なら-0を,0なら0を設定する.
x.setInf(符号) BigF型のオブジェクトxに無限大を代入する.符号はint型で,正なら+∞を,負なら-∞を,0なら∞を設定する.
x.setNan() BigF型のオブジェクトxにNan(Not a number)を設定する.
■ 基本的な演算
x.setAdd(v1,v2) v1+v2(共にBigF型のオブジェクト)の値をxに代入する.
x.setSub(v1,v2) v1-v2(共にBigF型のオブジェクト)の値をxに代入する.
x.setMul(v1,v2) v1*v2(共にBigF型のオブジェクト)の値をxに代入する.
x.setDiv(v1,v2) v1/v2(共にBigF型のオブジェクト)の値をxに代入する.
x.setAdd(v) BigF型のオブジェクトxにBigF型のオブジェクトvの値を加算する.(計算結果はxの値になる)
x.setSub(v) BigF型のオブジェクトxからBigF型のオブジェクトvの値を引く.(計算結果はxの値になる)
x.setMul(v) BigF型のオブジェクトxにBigF型のオブジェクトvの値を掛ける.(計算結果はxの値になる)
x.setDiv(v) BigF型のオブジェクトxをBigF型のオブジェクトvの値で割る.(計算結果はxの値になる)
x.setNeg(v) BigF型のオブジェクトvの符号を反転した値をxに代入する.
x.setInv(v) BigF型のオブジェクトvの逆数をxに代入する.
x.setAbs(v) BigF型のオブジェクトvの絶対値をxに代入する.
x.setPow(v,p) BigF型のオブジェクトvのp乗をxに代入する.(unsigned long p)
x.setFact(n) nの階乗をxに代入する.(nはint,long,unsigned long)
■ 関数
x.setSqrt(v) BigF型のオブジェクトvの平方根をxに代入する.
x.setPi() 円周率をxに代入する.
x.setExp(v) e^v(vはBigF型)の値をxに代入する.
x.setExp2(v) 2^v(vはBigF型)の値をxに代入する.
x.setExp10(v) 10^v(vはBigF型)の値をxに代入する.
x.setLog(v) BigF型のオブジェクトvの対数(底e)をxに代入する.
x.setLog2(v) BigF型のオブジェクトvの対数(底2)をxに代入する.
x.setLog10(v) BigF型のオブジェクトvの対数(底10)をxに代入する.
x.setSin(v) 正弦関数sin(v)(vはBigF型)の値をxに代入する.
x.setCos(v) 余弦関数cos(v)(vはBigF型)の値をxに代入する.
x.setTan(v) 正接関数tan(v)(vはBigF型)の値をxに代入する.
x.setSec(v) 正割関数sin(v)(vはBigF型)の値をxに代入する.
x.setCsc(v) 余割関数cos(v)(vはBigF型)の値をxに代入する.
x.setCot(v) 余接関数tan(v)(vはBigF型)の値をxに代入する.
x.setAsin(v) 逆正弦関数asin(v)(vはBigF型)の値をxに代入する.
x.setAcos(v) 逆余弦関数acos(v)(vはBigF型)の値をxに代入する.
x.setAtan(v) 逆正接関数atan(v)(vはBigF型)の値をxに代入する.
x.setSinh(v) 双曲線関数sinh(v)(vはBigF型)の値をxに代入する.
x.setCosh(v) 双曲線関数cosh(v)(vはBigF型)の値をxに代入する.
x.setTanh(v) 双曲線関数tanh(v)(vはBigF型)の値をxに代入する.
x.setSech(v) 双曲線関数sech(v)(vはBigF型)の値をxに代入する.
x.setCsch(v) 双曲線関数csch(v)(vはBigF型)の値をxに代入する.
x.setCoth(v) 双曲線関数coth(v)(vはBigF型)の値をxに代入する.
x.setAsinh(v) 逆双曲線関数sinh(v)(vはBigF型)の値をxに代入する.
x.setAcosh(v) 逆双曲線関数cosh(v)(vはBigF型)の値をxに代入する.
x.setAtanh(v) 逆双曲線関数tanh(v)(vはBigF型)の値をxに代入する.
x.setGamma(v) ガンマ関数Γ(v)(vはBigF型)の値をxに代入する.
x.setZeta(v) ゼータ関数Ζ(v)(vはBigF型)の値をxに代入する.
■ 述語(比較など)
x == y BigF型のオブジェクトx,yの値が等しければtrue,それ以外はfalseを返す.
x != y BigF型のオブジェクトx,yの値が異なればtrue,それ以外はfalseを返す.
x > y BigF型のオブジェクトx,yの値を比較し,x>yならばtrue,それ以外はfalseを返す.
x < y BigF型のオブジェクトx,yの値を比較し,x
x >= y BigF型のオブジェクトx,yの値を比較し,x>=yならばtrue,それ以外はfalseを返す.
x <= y BigF型のオブジェクトx,yの値を比較し,x<=yならばtrue,それ以外はfalseを返す.
x.isZero(符号) BigF型のオブジェクトxがゼロならばtrue,それ以外はfalseを返す.符号はint型で,正ならば+0,負ならば-0,0ならば0であることを判定する.
x.isInf(符号) BigF型のオブジェクトxが無限大ならばtrue,それ以外はfalseを返す.符号はint型で,正ならば+∞,負ならば-∞,0ならば∞であることを判定する.

MPFRの利用

 GMP(Gnu MP)は基本的には算術(加減乗除)の演算のみを提供しますが,各種の高度な関数(指数関数,対数関数,三角関数など)の値を計算するための機能はありません.そこで,GMPを利用して高度な関数を計算するためのライブラリ MPFR が作られました.
 
GNU MPFRのサイト: http://www.mpfr.org/
 
 MPFRの使い方はGMPに倣っており,mpfr_t 型のオブジェクトを用いて計算処理を実行します.MPFR用の各種関数もGMPのものと類似しており,同じような使い方ができます.
 
【各種計算のための関数】 (一部の代表的なもの)

算術演算 書式 意味
加算 mpfr_add(x,a,b,丸め指定) x = a + b
減算 mpfr_sub(x,a,b,丸め指定) x = a – b
乗算 mpfr_mul(x,a,b,丸め指定) x = a * b
除算 mpfr_div(x,a,b,丸め指定) x = a / b
べき乗 mpfr_pow(x,a,b,丸め指定) x = a ^ b
指数・対数関数 書式 意味
e^n mpfr_exp(x,n,丸め指定) x = e ^ n
2^n mpfr_exp2(x,n,丸め指定) x = 2 ^ n
10^n mpfr_exp10(x,n,丸め指定) x = 10 ^ n
log e n mpfr_log(x,n,丸め指定) x = log e n
log 2 n mpfr_log2(x,n,丸め指定) x = log 2 n
log 10 n mpfr_log10(x,n,丸め指定) x = log 10 n
三角関数 書式 意味
正弦関数 mpfr_sin(y,x,丸め指定) y = sin(x)
余弦関数 mpfr_cos(y,x,丸め指定) y = cos(x)
正接関数 mpfr_tan(y,x,丸め指定) y = tan(x)
逆正弦関数 mpfr_asin(y,x,丸め指定) y = asin(x)
逆余弦関数 mpfr_acos(y,x,丸め指定) y = acos(x)
逆正接関数 mpfr_atan(y,x,丸め指定) y = atan(x)

GMP利用の流れ

1) 値を保持するオブジェクトの宣言
 値を保持するオブジェクトには mpz_t(整数型)mpq_t(有理数型)mpf_t(浮動小数点数型)の3つがあり,必要に応じてそれらの型のオブジェクトを宣言します.
 
例.有理数型のオブジェクトの宣言: mpq_t a, b, c;
 
2) オブジェクトの初期化
 GMPのオブジェクトは計算に使用する前(値を格納する前)に初期化処理をする必要があります.
 
例.有理数型オブジェクトの初期化:
 mpq_init(a);
 mpq_init(b);
 mpq_init(c);

同様に mpz_init, mpf_init 関数があります.
 
3) オブジェクトへの値の格納(代入)
■ mpz_t(整数)オブジェクト x への値の格納
 mpz_set_ui( mpz_t x, unsigned long v ) : 符号なしlong型のvを代入
 mpz_set_si( mpz_t x, long v ) : long型のvを代入
 mpz_set_str( mpz_t x, const char *v, inv base ) :
   base進法の基数で表現された文字列としての整数vを解釈して代入
 
■ mpq_t(有理数)オブジェクト x への値の格納
 mpq_set_ui( mpz_t x, unsigned long v1, unsigned long v2 ) :
   符号なしlong型で表現された有理数 v1/v2 を代入
 mpq_set_si( mpz_t x, long v1, unsigned long v2 ) :
   同じく v1/v2 を代入
 mpq_set_d( mpz_t x, double v ) : double型の v を代入
 mpq_set_str( mpz_t x, const char *v, inv base ) :
   base進法の基数で表現された文字列としての有理数vを解釈して代入

同様に mpf_t 型のオブジェクトにも値を格納する関数があります.
 
4) 計算処理
■ 加算: r = v1 + v2
 mpz_add(r,v1,v2), mpq_add(r,v1,v2), mpf_add(r,v1,v2)
■ 減算: r = v1 – v2
 mpz_sub(r,v1,v2), mpq_sub(r,v1,v2), mpf_sub(r,v1,v2)
■ 乗算: r = v1 * v2
 mpz_mul(r,v1,v2), mpq_mul(r,v1,v2), mpf_mul(r,v1,v2)
■ 除算: r = v1 / v2
 mpz_div(r,v1,v2), mpq_div(r,v1,v2), mpf_div(r,v1,v2)
その他…
 
5) 出力(変換)
■ 文字列への変換
例.mpz_t(整数型)のオブジェクト x を char *s に変換する
 mpz_get_str( char *s, int base, mpz_t x )
同様に mpq_t, mpf_t 型のオブジェクトを文字列に変換することができます.
 
その他にも,long, unsigned long, double 型に変換する関数もあります.

日付と時間(2)

「日付と時刻」をデータとして扱う方法です.Date クラスのオブジェクトは生成時にその時点の日付&時刻を取得しますが,ここで紹介する Calendar クラスのオブジェクトは日付&時刻を1つのデータと見て日数計算(「〜日あと」とか「〜週間前」,「〜時間後」とかの計算)をするためのものです.
 下のサンプルプログラム “CalendarTest1.java” では最初に「2014/01/01,00:00:00」の日付をデータとして用意して「〜日後」「〜時間後」のような計算をしている例です.
 set() メソッドで日付や時刻を設定し,add() メソッドで日数や時間を加算し,get() メソッドで日付や時刻を取り出します.

import java.util.*;

class CalendarTest1 {
	public static void main( String argv[] ) {

		int y, m, d, wd2, h, min, sec;
		Calendar cal = Calendar.getInstance();
		String wd[] = { "日", "月", "火", "水", "木", "金", "土" };

		/* 2014/01/01, 00:00:00 */
		cal.set(Calendar.YEAR,2012);
		cal.set(Calendar.MONTH,1-1);
		cal.set(Calendar.DATE,1);
		cal.set(Calendar.HOUR_OF_DAY,0);
		cal.set(Calendar.MINUTE,0);
		cal.set(Calendar.SECOND,0);

		/* after 86,400 seconds */
		cal.add(Calendar.SECOND,86400);
		y = cal.get(Calendar.YEAR);
		m = cal.get(Calendar.MONTH) + 1;
		d = cal.get(Calendar.DATE);
		wd2 = cal.get(Calendar.DAY_OF_WEEK) - 1;
		System.out.printf("%d/%02d/%02d(%s)\n",y,m,d,wd[wd2]);

		/* after 12 Months */
		cal.add(Calendar.MONTH,12);
		y = cal.get(Calendar.YEAR);
		m = cal.get(Calendar.MONTH) + 1;
		d = cal.get(Calendar.DATE);
		wd2 = cal.get(Calendar.DAY_OF_WEEK) - 1;
		System.out.printf("%d/%02d/%02d(%s)\n",y,m,d,wd[wd2]);

		/* after 28 Days */
		cal.add(Calendar.DATE,28);
		y = cal.get(Calendar.YEAR);
		m = cal.get(Calendar.MONTH) + 1;
		d = cal.get(Calendar.DATE);
		wd2 = cal.get(Calendar.DAY_OF_WEEK) - 1;
		System.out.printf("%d/%02d/%02d(%s)\n",y,m,d,wd[wd2]);

		/* after 24 Hours */
		cal.add(Calendar.HOUR_OF_DAY,24);
		y = cal.get(Calendar.YEAR);
		m = cal.get(Calendar.MONTH) + 1;
		d = cal.get(Calendar.DATE);
		wd2 = cal.get(Calendar.DAY_OF_WEEK) - 1;
		System.out.printf("%d/%02d/%02d(%s)\n",y,m,d,wd[wd2]);

		/* after 31,536,000 Seconds */
		cal.add(Calendar.SECOND,31536000);
		y = cal.get(Calendar.YEAR);
		m = cal.get(Calendar.MONTH) + 1;
		d = cal.get(Calendar.DATE);
		wd2 = cal.get(Calendar.DAY_OF_WEEK) - 1;
		System.out.printf("%d/%02d/%02d(%s)\n",y,m,d,wd[wd2]);
	}
}

 このプログラムを実行すると,次のような内容が表示されます.

2012/01/02(月)
2013/01/02(水)
2013/01/30(水)
2013/01/31(木)
2014/01/31(金)

文字列⇔数値の変換

int, long, double といった数値の型の変数と文字列(String)オブジェクトの間で値の変換をすることは,実際のプログラミングでよく行われます.
 
数値から文字列に変換するには valueOf() メソッドを使います.また逆に文字列として表現されている数値を解釈して int, long, double などの型の変数に値を入れるには parse型名() メソッドを用います.
 
これらのメソッドを用いたサンプルを “valueConv1.java” に示します.

class valueConv1 {
	public static void main( String argv[] ) {
		int i = 1;
		long l = 2;
		double f = 3.4;
		String is, ls, fs;

		is = String.valueOf(i); //    int -> String
		ls = String.valueOf(l); //   long -> String
		fs = String.valueOf(f); // double -> String
		System.out.printf("\'%s\' , \'%s\' , \'%s\'\n",is,ls,fs);

		i = Integer.parseInt(is);   // String -> int
		l = Long.parseLong(ls);	    // String -> long
		f = Double.parseDouble(fs); // String -> double
		System.out.printf("%d , %d , %.1f\n",i,l,f);
	}
}

これを実行すると次のような表示になります.

'1' , '2' , '3.4'
1 , 2 , 3.4