数学

2023

2023年になりました。2023 に関係する計算をしてみます。

Prime Curios! から

素数に関して、興味深い事実を多く掲載している Prime Curios! で2023を調べてみます。以下が該当しました。サイトは英語ですが、日本語に訳しました。

素数 813258173412030282336987547007 の後ろに、ちょうど 2023 個の合成数が続く。この素数は、2023 個の合成数が後に続く最小の数となる。

https://primes.utm.edu/curios/page.php?short=2023

擬素数を判定する

813258173412030282336987547007 は、30桁もあります。素数判定を行う、Baillie–PSW の素数テストと呼ばれる方法があります。この判定方法は、以下の性質を持ちます。

  • 合成数と判定されれば、その数は合成数
  • 素数と判定されても、その数が合成数であることがある(擬素数)。

C や C++ で多倍長演算を行うことができる GMP(GNU Multi-Precision)ライブラリがこの判定方法を関数として提供しています。なお、GMP については、この記事で紹介しています。

mpz_probab_prime_p

以下が、GMP が提供している関数 mpz_probab_prime_p の仕様です。

int mpz_probab_prime_p (const mpz t n, int reps)

引数

  • n : GMP が提供している多倍長の整数型の変数
  • reps : Baillie–PSW の繰り返し回数

戻り値

  • 2 : 素数と判定
  • 1 : 擬素数と判定
  • 0 : 合成数と判定

仕様

  • n の素数判定を行う。数が大きくなると Baillie–PSW を使って判定する。
  • 擬素数と判定された場合、それが合成数である確率は、4-reps 以下となる。計算速度と誤る確率を考慮すると reps は、15 から 50 の値が良い。(GMP マニュアルより)

素数判定プログラム(Baillie–PSW 版)

上記、関数を使って素数判定をするプログラムを作りました。どれだけ大きな数でも判定できます。繰り返し数 reps は、50 としました。誤って合成数を素数と判定する確率は、かなり低くなります。趣味で計算する場合、ほぼ 0 と考えています。

判定したい数は、プログラムの最初の引数で与えるか、標準入力で与えます。

#include <stdio.h>
#include <gmp.h>

#define REPS 50

int main(int argc, char *argv[])
{
	int ret;
	mpz_t z;

	mpz_init(z);

	if (argc > 1) {
		mpz_set_str(z, argv[1], 10);
	} else {
		mpz_inp_str(z, stdin, 10);
	}

	ret = mpz_probab_prime_p(z, REPS);

	mpz_out_str(stdout, 10, z);

	if (ret == 2) {
		printf(" is prime number.\n");
	} else if (ret == 1) {
		printf(" may be prime number.\n");
	} else {
		printf(" is composite number.\n");
	}

	mpz_clear(z);

	return 0;
}

GMP ライブラリをリンクする必要があります。gcc を使う場合は、以下のコマンドとなります。

gcc -o isPrime_gmp isPrime_gmp.c -lgmp

2023 について追試験する

813258173412030282336987547007 から 2023 個合成数が続くことを確認してみました。

#include <stdio.h>
#include <gmp.h>

#define REPS 50

char number[] = "813258173412030282336987547007";

int main(int argc, char *argv[])
{
	int i;
	int ret;
	mpz_t z;

	mpz_init(z);

	mpz_set_str(z, number, 10);

	for (i = 0; i <= 2024; ++i) {
		ret = mpz_probab_prime_p(z, REPS);
		if (ret == 2) {
			mpz_out_str(stdout, 10, z);
			printf(" is prime number.\n");
		} else if (ret == 1) {
			mpz_out_str(stdout, 10, z);
			printf(" may be prime number.\n");
		}
		mpz_add_ui(z, z, 1UL);
	}

	mpz_clear(z);

	return 0;
}

このプログラムを動かすと、以下の出力となります。

813258173412030282336987547007 may be prime number.
813258173412030282336987549031 may be prime number.

813258173412030282336987547007 が擬素数と判定されました。その後に2023個の合成数があります(出力はしていない)。その後の 813258173412030282336987547031 が擬素数と判定されました。

最後に

擬素数という制限で、大きな数でも素数判定ができるプログラムを作りました。

今年も、いろいろプログラムを書いて、計算しようと考えています。

COMMENT

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

CAPTCHA