[ GO FOR IT ] 2) 実数の階乗

問題:

ある検索サイトに5!と入力するとその計算結果である120が表示されます。
その検索サイトに2.5!と入力するとなんと3.32335097と表示されます。
さらにその検索サイトに(-1.9)!と入力すると-10.5705641と表示されます。
きっとそれらの仕組みはとても難しくて企業秘密に違いないので是非ともこれらを実行するプログラムを作ってほしい。
ただし、君のPCは古いのでネットワークや便利で高度な数学関数は入っていません。
入っている数学関数はsin,cos,tan,log,pow,floorなどの初歩的な関数のみです、残念ながら。

i)入力された整数a(0<=a<=10)の階乗を求めるプログラムを作ってください。 ii)入力された実数a(0<=a<=10)の階乗を求めるプログラムを作ってください。 iii)入力された実数a(-1.9<=a<=-1.1)の階乗を求めるプログラムを作ってください。 回答(C++プログラムコード):

#include
#include
#include
#include
#include 

using namespace std;

// define the constants
static const int g=7;
static const double pi =3.1415926535897932384626433832795028841972 ;
static const double p[g+2] = {0.99999999999980993, 676.5203681218851,
-1259.1392167224028, 771.32342877765313, -176.61502916214059,
12.507343278686905, -0.13857109526572012, 9.9843695780195716e-6,
1.5056327351493116e-7};

// define the Lanczos_approximation of gamma function
complex gamma( complex z)
{
	if ( real(z)<0.5 ) 
	{
		return pi / (sin(pi*z)*gamma(1.0-z));
	}
	z -= 1.0;
	complex x=p[0];
	for (int i=1; i(i,0));
	}
	complex t = z + (g + 0.5);
	return sqrt(2*pi) * pow(t,z+0.5) * exp(-t) * x;
}

int main()
{
	double r,i;
	cout<<"Please input the real part of the complex number:"<>r;
	cout<<"Please input the imaginary number of the complex number:"<>i;
	cout << "The factorial of "<(r,i)<<" is "<(r+1,i)) << endl; 
	system("PAUSE");
	return 0;
}

プログラムコード:LifeClock.cpp
URL: https://leybreeze.com/blog/wp-content/uploads/2012/02/RealNumberFactorial.cpp

回答できた問題の出力:
入力によって違います。

アルゴリズムの簡単な説明:
実数の階乗と言うと、ガンマ関数のことです。
使用可能な数学関数はsin,cos,tan,log,pow,floorなどの初歩的な関数のみですから、Lanczos approximationというの近似法は使えます。
(ご参考まで:http://en.wikipedia.org/wiki/Lanczos_approximation )

実行方法:RealNumberFactorial.exe (msvcp100d.dllは必要です。)実行して実数の実部と虚部を入力してください
URL: https://leybreeze.com/blog/wp-content/uploads/2012/02/RealNumberFactorial.exe

実行環境:Windows XP/Vista/7

ライセンス:GPLv3

[ GO FOR IT ] 1) 人生の時計

問題:

あなたの一生を24時間にたとえると今日は何時何分何秒ですか?
ただしあなたはあなたの誕生日(a年b月c日)の0時ちょうどに生まれてn歳まで生きる(n歳のときは生きていてn+1歳にはなれない)とし、bとcは一般的な月日の範囲とします。

i) 1990<=a<=2000,n=80のとき、今日は何時何分何秒ですか?
ii) 1900<=a<=2000,n=200のとき、今日は何時何分何秒ですか?

回答(C++プログラムコード):

#include
#include
#include
#include

using namespace std;

// check if the year is a leap year
bool is_leap_year(int year)
{
	if (year%4==0 && year%100!=0 || year%400==0)
		return true;
	else
		return false;
}

// check if the day is valid
bool is_birthday_valid(int year, int month, int day)
{
	switch(month)
	{
	case 1:
		if (day>0 && day<32)
			return true;
		else
			return false;
		break;
	case 2:
		if (is_leap_year(year))
		{
			if (day>0 && day<30)
				return true;
			else
				return false;
		}
		else
		{
			if (day>0 && day<29)
				return true;
			else
				return false;
		}
		break;
	case 3:
		if (day>0 && day<32)
			return true;
		else
			return false;
		break;
	case 4:
		if (day>0 && day<31)
			return true;
		else
			return false;
		break;
	case 5:
		if (day>0 && day<32)
			return true;
		else
			return false;
		break;
	case 6:
		if (day>0 && day<31)
			return true;
		else
			return false;
		break;
	case 7:
		if (day>0 && day<32)
			return true;
		else
			return false;
		break;
	case 8:
		if (day>0 && day<32)
			return true;
		else
			return false;
		break;
	case 9:
		if (day>0 && day<31)
			return true;
		else
			return false;
		break;
	case 10:
		if (day>0 && day<32)
			return true;
		else
			return false;
		break;
	case 11:
		if (day>0 && day<31)
			return true;
		else
			return false;
		break;
	case 12:
		if (day>0 && day<32)
			return true;
		else
			return false;
		break;
	}
	return true;
}

// calculate days after the given day, not including the given day (return 0 when given 12/31)
int calculate_days_after(bool leap, int month, int day)
{
	int days=0;
	int days_of_month[]={31,28,31,30,31,30,31,31,30,31,30,31};
	if (leap)
	{
		days_of_month[1]=29;
	}
	if (month<12)
		for (int i=month;i<12;i++)
		{
			days+=days_of_month[i];
		}
	days+=(days_of_month[month-1]-day);
	return days;
}

// calculate days before the given day, including the given day (return 366 when given a leap year's 12/31)
int calculate_days_before(bool leap, int month, int day)
{
	int days=0;
	int days_of_month[]={31,28,31,30,31,30,31,31,30,31,30,31};
	if (leap)
	{
		days_of_month[1]=29;
	}
	for (int i=0;i1903)
			return (endyear-1904)/4+1;
		else
			return 0;
	}
	else if (is_leap_year(startyear))
	{
		return (endyear-startyear)/4+1;
	}
	else if (is_leap_year(startyear+1))
	{
		return (endyear-startyear-1)/4+1;
	}
	else if (is_leap_year(startyear+2))
	{
		return (endyear-startyear-2)/4+1;
	}
	else if (is_leap_year(startyear+3))
	{
		return (endyear-startyear-3)/4+1;
	}
	return 0;
}

// calculate the total days in n years
int calculate_total_days(int startyear, int n, int month, int day)
{
	return (n-1)*365+calculate_leap_year(startyear+1, startyear+n-1)+
		calculate_days_after(is_leap_year(startyear),month,day)+calculate_days_before(is_leap_year(startyear+n),month,day);
}

int calculate_current_days(int startyear, int startmonth, int startday, int year, int month, int day)
{
	return (year-startyear-1)*365+calculate_leap_year(startyear+1, year-1)+
		calculate_days_after(is_leap_year(startyear),startmonth,startday)+calculate_days_before(is_leap_year(year),month,day);
}

int main()
{
	// declaration
	struct tm *date;
	time_t now;
	int year, month, day; // current time
	int birthyear,birthmonth,birthday; // birthday
	float total_days; // total days of n years
	float current_days; // total days since birthday
	int current_seconds; // time in 24 hours
	int current_minutes;
	int current_hours;
	int n; // life span

	// get current time
	time(&now);
	date = localtime(&now);
	year = date->tm_year + 1900;
	month = date->tm_mon + 1;
	day = date->tm_mday;

	// input data
	int problemnum;
	cout<<"Please input problem number(1-2):"<>problemnum; // select problem number
	while(!(problemnum==1 || problemnum==2));
	if (problemnum==1)
	{
		n=80; // set life span
		cout<<"Please input the year you birth(1990-2000):"<>birthyear; // get birthyear
		while(birthyear<1990 || birthyear>2000);
	}
	else
	{
		n=200; // set life span
		cout<<"Please input the year you birth(1900-2000):"<>birthyear; // get birthyear
		while(birthyear<1900 || birthyear>2000);
	}
	cout<<"Please input the month you birth:"<>birthmonth; // get birthmonth
	while(birthmonth<1 || birthmonth>12);
	cout<<"Please input the day you birth:"<>birthday; // get birthday
	while(!is_birthday_valid(birthyear,birthmonth,birthday)); // check if the birthday is valid

	// calculate the result
	current_days=calculate_current_days(birthyear,birthmonth,birthday,year,month,day); // calculate total days since birthday
	total_days=calculate_total_days(birthyear,n,birthmonth,birthday); // calculate total days of n years since birthday
	current_seconds=(int)(current_days/total_days*3600*24); // calculate the time in 24 hours
	current_minutes=current_seconds/60;
	current_hours=current_minutes/60;
	current_seconds=current_seconds%60;
	current_minutes=current_minutes%60;

	// output the result
	cout<<"あなたの一生を24時間にたとえると今日は  "<

プログラムコード:LifeClock.cpp
URL: https://leybreeze.com/blog/wp-content/uploads/2012/02/LifeClock.cpp

回答できた問題の出力:
入力によって違います。

アルゴリズムの簡単な説明:
生年月日と現在の日付を取得
誕生日からn歳までの日数と誕生日から今までの日数を計算
24時間に変換
秒:誕生日から今までの日数/誕生日からn歳までの日数*3600*24
秒をよって分と時を計算

実行方法:LifeClock.exe 実行して小問の番号と生年月日を入力してください
URL: https://leybreeze.com/blog/wp-content/uploads/2012/02/LifeClock.exe

実行環境:Windows XP/Vista/7

ライセンス:GPLv3