스칼라 263 자
새로운 요구 사항에 맞게 업데이트되었습니다. 코드의 25 %는 아래의 소수를 계산하기위한 합리적인 상한값을 찾는 데 사용됩니다.
object P extends App{
def c(M:Int)={
val p=collection.mutable.BitSet(M+1)
p(2)=true
(3 to M+1 by 2).map(p(_)=true)
for(i<-p){
var j=2*i;
while(j<M){
if(p(j))p(j)=false
j+=i}
}
p
}
val i=args(0).toInt
println(c(((math.log(i)*i*1.3)toInt)).take(i).mkString("\n"))
}
나도 체를 얻었다.
다음은 분석 비용을 계산하지 않은 계산 비용에 대한 경험적 테스트입니다.
object PrimesTo extends App{
var cnt=0
def c(M:Int)={
val p=(false::false::true::List.range(3,M+1).map(_%2!=0)).toArray
for (i <- List.range (3, M, 2)
if (p (i))) {
var j=2*i;
while (j < M) {
cnt+=1
if (p (j))
p(j)=false
j+=i}
}
(1 to M).filter (x => p (x))
}
val i = args(0).toInt
/*
To get the number x with i primes below, it is nearly ln(x)*x. For small numbers
we need a correction factor 1.13, and to avoid a bigger factor for very small
numbers we add 666 as an upper bound.
*/
val x = (math.log(i)*i*1.13).toInt+666
println (c(x).take (i).mkString("\n"))
System.err.println (x + "\tcount: " + cnt)
}
for n in {1..5} ; do i=$((10**$n)); scala -J-Xmx768M P $i ; done
다음과 같은 계산으로 이어집니다.
List (960, 1766, 15127, 217099, 2988966)
점수를 계산하는 방법을 잘 모르겠습니다. 5자를 더 쓸 가치가 있습니까?
scala> List(4, 25, 168, 1229, 9592, 78498, 664579, 5761455, 50847534).map(x=>(math.log(x)*x*1.13).toInt+666)
res42: List[Int] = List(672, 756, 1638, 10545, 100045, 1000419, 10068909, 101346800, 1019549994)
scala> List(4, 25, 168, 1229, 9592, 78498, 664579, 5761455, 50847534).map(x=>(math.log(x)*x*1.3)toInt)
res43: List[Int] = List(7, 104, 1119, 11365, 114329, 1150158, 11582935, 116592898, 1172932855)
n이 클수록 해당 범위에서 계산이 약 16 % 감소하지만 점수 공식에 대해서는 당연한 요소를 고려하지 않습니까?
새로운 Big-O 고려 사항 :
1000, 10 000, 100 000 소수 등을 찾으려면 소수의 밀도에 대한 공식을 사용합니다.
따라서 1 ~ 6 => NPrimes (10 ^ i)의 값 i는 9399, 133768 ... 외부 루프의 횟수로 실행됩니다.
나는 1.01 대신에 1.5보다 높은 지수를 제안한 Peter Taylor의 의견을 통해이 O- 함수를 반복적으로 찾았습니다.
def O(n:Int) = (math.pow((n * math.log (n)), 1.01)).toLong
O : (n : 정수)
val ns = List(10, 100, 1000, 10000, 100000, 1000*1000).map(x=>(math.log(x)*x*1.3)toInt).map(O)
ns : 목록 [긴] = 목록 (102, 4152, 91532, 1612894, 25192460, 364664351)
That's the list of upper values, to find primes below (since my algorithm has to know this value before it has to estimate it), send through the O-function, to find similar quotients for moving from 100 to 1000 to 10000 primes and so on:
(ns.head /: ns.tail)((a, b) => {println (b*1.0/a); b})
40.705882352941174
22.045279383429673
17.62109426211598
15.619414543051187
14.47513863274964
13.73425213148954
1.01을 지수로 사용하면 몫입니다. 카운터가 경험적으로 찾는 것은 다음과 같습니다.
ns: Array[Int] = Array(1628, 2929, 23583, 321898, 4291625, 54289190, 660847317)
(ns.head /: ns.tail)((a, b) => {println (b*1.0/a); b})
1.799140049140049
8.051553431205189
13.649578085909342
13.332251210010625
12.65003116535112
12.172723833234572
처음 두 값은 특이 치입니다. 왜냐하면 작은 값 (최대 1000)에 대한 추정 공식을 지속적으로 수정했기 때문입니다.
Peter Taylors의 제안 1.5는 다음과 같습니다.
245.2396265560166
98.8566987153728
70.8831374743478
59.26104390040363
52.92941829568069
48.956394784317816
이제 내 가치는 다음과 같습니다.
O(263)
res85: Long = 1576
그러나 나는 O 값을 관찰 된 값에 얼마나 가깝게 사용할 수 있는지 잘 모르겠습니다.