数学

8桁日付の「素数の日」を考えます

喜んでいるわたし

前回は、1年に1回の記念日という意味で「素数の日」を考えてみました。西暦+月+日の8桁の自然数が素数になる日を素数の日と呼ぶ方が一般的かもしれません。今回は、8桁日付の素数について、計算してみました。

一般的な素数の日

「素数の日」を検索すると、西暦+月+日の8桁の自然数が素数になる日がでてきます。2022年は、この意味での素数の日が以下の23日あります。

20220103
20220119
20220121
20220127
20220217
20220307
20220311
20220323
20220331
20220407
20220517
20220601
20220619
20220713
20220817
20220821
20220901
20220923
20221009
20221027
20221127
20221213
20221231

2023年もこの意味での素数は以下の18日あります。

20230103
20230109
20230121
20230201
20230219
20230303
20230411
20230517
20230519
20230619
20230621
20230831
20230919
20231011
20231017
20231023
20231129
20231203

その日が素数になっているという意味での素数の日は、数が多すぎてありがたみが少ないと感じます。

左切り捨て素数の8桁日付を探す

前回と同様に左切り捨て可能素数である日付を探します。切り捨て可能素数については、こちらに定義と例を示しています。途中の桁に0を含む場合は、左切り捨て可能素数と呼びませんが、以下のプログラムでは、0を含む日付も出力しています。

左切り捨て可能素数となる8桁日付を出力する C プログラムは以下となります。素数判定を行う回数が多いため、エラトステネスの篩を使いました。

#include <stdio.h>

#define N 100000000
unsigned char is_prime_table[N+1];
#define is_prime(n) (is_prime_table[(n)])

int daytable [2][12] = {
	{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31},
	{31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
};

void generate_is_prime_table(int n)
{
	int i, j;

	for (i = 2; i <= n; ++i) {
		is_prime_table[i] = 1;
	}

	for (i = 2; i * i <= n; ++i) {
		if (is_prime_table[i] == 1) {
			for (j = i + i; j <= n; j += i) {
				is_prime_table[j] = 0;
			}
		}
	}

	return;
}

int is_satisfied(int number)
{
	int ret_val = 1;
	int mask, check_number;

	mask = 10000000;

	if (is_prime(number) == 0) {
		ret_val = 0;
	}

	check_number = number % mask;
	while (mask >= 10) {
		if (is_prime(check_number) == 0) {
			ret_val = 0;
			break;
		}
		mask = mask / 10;
		check_number = number % mask;
	}

	return ret_val;
}

int main(void)
{
	int year, month, day;
	int leap;
	int date;

	generate_is_prime_table(N);

	for (year = 1000; year <= 9999; ++year) {
		leap = (year % 400 == 0)||((year % 100 != 0)&&(year % 4 == 0));
		for (month = 1; month <= 12; ++month)  {
			for (day = 1; day <= daytable[leap][month - 1]; ++day) {
				date = year * 10000 + month * 100 + day;
				if (is_satisfied(date) == 1) {
					printf("%8d\n", date);
				}
			}
		}
	}

	return 0;
}

1000年から9999年まで、458日しか見つかりませんでした。2000年から2100年までの101年を考えても以下の28日しかありません。

20000107
20000503
20010223
20010313
20031223
20060107
20070823
20100907
20130223
20190523
20190823
20300317
20360317
20400307
20400823
20480107
20600317
20660617
20700103
20700223
20700307
20700523
20721013
20910103
20930113
21000313
21000907
21050503

今は、この素数の日の長い中間にいます。わたしは、2019年8月23日にこのことを計算して知っていましたが、発表する手段を持っていませんでした。このブログで書けて少しすっきりしました。この意味での次の素数の日は、2030年3月17日になります。この日をどう迎えるのか楽しみです。

あと、本来の左切り捨て可能素数は、0 を含みません。この意味で8桁日付で、左き捨て可能素数は、以下の6日しかありません。非常に少ないです。すべて12月23日になるのは、偶然ではありません(前回の記事を参照してください)。さすがに3338年12月23日は、この世界がどうなっているか想像できません。

33381223
36631223
43381223
63381223
66631223
84261223

最後に

2回続けて素数の日について、いろいろ計算しました。その日付が素数という意味では、多く見つかりましたが、左切り捨て可能という条件を付けると、ありがたい少ない頻度になりました。

前回同様、プログラムで計算して、このようなことが分かると楽しくなります。

COMMENT

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA