This question relates to euler project sum-of-primes, and Stream.view, but there is a bit of a twist. I want to calculate the sum of all the primes below two million. I create a generator of prime numbers defined as:
lazy val primes: Stream[Int] = 2 #:: Stream.from(3).filter(i =>
primes.takeWhile(j => j * j <= i).forall(i % _ > 0))
I wrote two tests, one using Stream[Int]#foldLeft and one using Stream[Int]#sum:
@Test
def testEuler010a {
primes.view.takeWhile(_ < 2000000).foldLeft(0L)(_ + _) mustEqual 142913828922L
}
@Test
def testEuler010b {
primes.view.takeWhile(_ < 2000000).sum mustEqual 142913828922L
}
testEuler010a
gives me the right answer while testEuler010b
does not with an answer of 1179908154
. I would expect that Stream[Int]#foldLeft(0L)(_ + _)
would be identical to Stream[Int].sum
, but it is not. Even if I materialize the Stream with a toList()
, I get he same discrepancy. Is it an incorrect assumption that those methods should give the same result?
I'm using Scala 2.9.1.final.
The problem seems to be overflow. These give the same results for me:
(primes map (_.longValue) takeWhile (_ < 2000000)).sum
(primes map (_.longValue) takeWhile (_ < 2000000)).foldLeft(0L)(_ + _)
I suppose the difference between sum
and foldLeft
is that the result type of sum
is the same as the type of the elements being summed over (as required by the Numeric trait), but foldLeft
can have a different result type, which you achieve by writing 0L
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With