【问题标题】:Scala Stream[Int]#foldLeft and Stream[Int]#sum give different resultsScala Stream[Int]#foldLeft 和 Stream[Int]#sum 给出不同的结果
【发布时间】:2012-01-18 02:13:07
【问题描述】:

这个问题与euler project sum-of-primes, and Stream.view 相关,但有一点不同。我想计算所有低于 200 万的素数之和。我创建了一个素数生成器,定义为:

lazy val primes: Stream[Int] = 2 #:: Stream.from(3).filter(i =>
  primes.takeWhile(j => j * j <= i).forall(i % _ > 0))

我写了两个测试,一个使用 Stream[Int]#foldLeft,一个使用 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 给了我正确的答案,而testEuler010b 没有给我1179908154 的答案。我希望Stream[Int]#foldLeft(0L)(_ + _)Stream[Int].sum 相同,但事实并非如此。即使我用toList() 实现流,我也会得到同样的差异。这些方法应该给出相同的结果是错误的假设吗?

我正在使用 Scala 2.9.1.final。

【问题讨论】:

  • 我不需要使用view。在这种情况下,性能没有提高,我也没有得到不同的结果。
  • 请注意142913828922L % (Int.MaxValue.toLong + 1) 等于sum 版本给出的值。

标签: scala


【解决方案1】:

问题似乎是溢出。这些对我来说是相同的结果:

(primes map (_.longValue) takeWhile (_ < 2000000)).sum
(primes map (_.longValue) takeWhile (_ < 2000000)).foldLeft(0L)(_ + _)

我想sumfoldLeft 之间的区别在于sum 的结果类型与被求和的元素的类型相同(根据Numeric trait 的要求),但foldLeft可以有不同的结果类型,你可以通过写0L来实现。

【讨论】:

    猜你喜欢
    • 2019-08-16
    • 2014-01-10
    • 2019-10-12
    • 2020-07-02
    • 2021-07-22
    • 1970-01-01
    • 1970-01-01
    • 2021-06-11
    • 1970-01-01
    相关资源
    最近更新 更多