简体   繁体   中英

value foreach is not a member of Int?

I am learning scala, and I need to print powers of 2 with its reciprocal from 0 to 20

What I am doing is

scala> for {
     | i <- 0 to 20
     | pow <- scala.math.pow(2, i).toInt
     | rec <- 1/pow
     | } println(pow + "\t" + rec)

But I see error as

<console>:13: error: value foreach is not a member of Int
       pow <- scala.math.pow(2, i).toInt
                                   ^

I know pow is not iterable, but how can I compute it before so that I reuse it?

Else, I am recomputing it as

scala> for(i <- 0 to 10) println(scala.math.pow(2, i).toInt + "\t" + 1/scala.math.pow(2,i))
1   1.0
2   0.5
4   0.25
8   0.125
16  0.0625
32  0.03125
64  0.015625
128 0.0078125
256 0.00390625
512 0.001953125
1024    9.765625E-4

Ugly, right?

When you use <- in a for comprehension, you need to be providing a type compatible with the output of the first such <- . Here, you create a Seq[Int] from the line i <- 0 to 20 , but then an Int from the next line. Instead, you can just assign the intermediate results, and yield a list at the end (that you can then print out or otherwise work with as you choose).

Also, you should note that by casting to an Int where you do, you ensure the reciprocal is calculated using integer division, which results in zero for the reciprocal for all but the first power - do the casting to Int in the yield so you have Double reciprocals.

Overall:

val result = for {
     i <- 0 to 20
     pow = scala.math.pow(2, i)
     rec = 1/pow
} yield (pow.toInt + "\t" + rec)

You can then print out the results using something like:

println(result.mkString("\n"))

Output will then be something like:

1   1.0
2   0.5
4   0.25
8   0.125
16  0.0625
32  0.03125
64  0.015625
128 0.0078125
256 0.00390625
512 0.001953125
1024    9.765625E-4
2048    4.8828125E-4
4096    2.44140625E-4
8192    1.220703125E-4
16384   6.103515625E-5
32768   3.0517578125E-5
65536   1.52587890625E-5
131072  7.62939453125E-6
262144  3.814697265625E-6
524288  1.9073486328125E-6
1048576 9.5367431640625E-7

Further, you could alter the yield to generate a list of tuples, then format however you choose later (decoupling formatting from generation):

val result = { ... // as before
} yield (i, pow, rec) // Could prove handy to keep the index, and keep pow as a Double for now

def printResults(results: List[(Int, Double, Double)], formatter: (Int, Double, Double) => String) = results forEach { case (n, pow, rec) =>
  println(formatter(n, pow, rec))
}

def egFormatter(n: Int, pow: Double, rec: Double) = s"For n = $n,\t 2^n = ${pow.toInt},\t reciprocal = $rec"

printResults(results, egFormatter)

A rather different approach, using Streams , offers some flexibility (length of output is chosen by the caller instead of being hard-coded) and memoization (after a value has been calculated it can then be retrieved rather than re-calculated).

// pts --> Powers of Two Stream
val pts: Stream[(Int,Double)] = (1,1.0) #:: fs.zipWithIndex.map{x=>
                                   val p = scala.math.pow(2, x._2+1);
                                   (p.toInt, 1/p)}

scala> pts.take(20).mkString("\n")
res11: String =
(1,1.0)
(2,0.5)
(4,0.25)
(8,0.125)
(16,0.0625)
(32,0.03125)
(64,0.015625)
(128,0.0078125)
(256,0.00390625)
(512,0.001953125)
(1024,9.765625E-4)
(2048,4.8828125E-4)
(4096,2.44140625E-4)
(8192,1.220703125E-4)
(16384,6.103515625E-5)
(32768,3.0517578125E-5)
(65536,1.52587890625E-5)
(131072,7.62939453125E-6)
(262144,3.814697265625E-6)
(524288,1.9073486328125E-6)

Output formatting is left as an exercise for the reader.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM