Scala 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的新注意事项:
为了找到1 000、10 000、100 000个素数,依此类推,我使用一个关于素数密度x =>(math.log(x)* x * 1.3的公式)来确定我正在运行的外循环。
因此,对于1到6中的值i => NPrimes(10 ^ i)运行9399、133768 ...乘以外循环。
我在彼得·泰勒(Peter Taylor)的评论的帮助下迭代地找到了这个O函数,他提出了更高的求幂值,而不是他建议的1.5:1.5
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:List [Long] =列表(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函数能与观测值有多接近。