かけ合わせるとレピュニットになる数を求めてみる

twitterで、

【急募】レピュニット素数を求めるプログラム - 言語・方式は問わない http://niku.name/20101016.html 暇なプログラマは挑戦してみてください.結構難しいですよ.できたら教えてください.

(引用元:http://twitter.com/niku_name/status/27551869199

というのを見て、ちょっと書いてみました。

プログラムはこちら→ http://apl.tmgn.jp/smpl/repunit/repunit.html

まず、レピュニットとは・・・

レピュニット (Repunit) とは全ての桁が 1である自然数のことである。つまり 1, 11, 111, 1111,...である。 Rn = (10n - 1) / 9 の形に表される。repeated unitを省略したものが名前の由来である。

(引用元:Wikipedia

つまり、1のゾロ目ですね。そして、「レピュニット素数」というのは、@niku_nameさんのBlog

掛け合わせるとレピュニットになる数.例えば 3*37=111 つまり 3 と 37 はレピュニット素数

と書かれていました。

なるほど。それを求めればいいんだな・・・と、少し考えてみると・・・

  • 掛け合わせるとレピュニットになるということは、レピュニットの約数を求めればいい
  • かけると1桁目が1になるには、1桁目が1, 3, 7, 9であればいい
  • あとは、それを回せばいい

そんな感じで、書けそうだったので書き出してみました。
まずは、レピュニットを求める関数。これはそのまま

function r(n){
	var d = 1;
	for(var i = 0; i < n; i++){
		d = d * 10;
	}
	return (d - 1) / 9;
}

つぎに、レピュニット素数を求める関数。

var elem = [1, 3, 7, 9];
function a(n){
	var repu = r(n);
	log("レピュニット(" + n + "):" + repu);
	
	var d = 0;
	var e = 0;
	var e2 = 0;
	do{
		for(var i = 0; i < elem.length; i++){
			e = (d * 10) + elem[i];
			e2 = repu / e;
			if(e > 1 && repu % e == 0){
				log(["------>", repu, " = ", e, " x ", e2].join("") );
			}
		}
		d++;
	}while(e < e2)
}

これで、15桁までは処理できるようになりました。
・・・しかし、16桁以上になるとなぜかレピュニット自体がおかしくなる。1桁目が2になったり。

ひょっとして、レピュニットの求め方は単純に1を文字列として並べて、evalで返してあげるほうがよかったりするんですかね?
・・・と、やってみると、16桁までいけました。

function r2(n){
	var _r = [];
	for(var i = 0; i < n; i++){
		_r.push(1);
	}
	return eval(_r.join(""));
}

でも、17桁はNG。
javascriptの限界なのかな・・・?