【问题标题】:Scala reduce and fold returns 0 instead of a valueScala reduce 和 fold 返回 0 而不是一个值
【发布时间】:2016-11-20 15:07:45
【问题描述】:

嘿,我有一个案例,我试图在 REPL 上运行它:

(1 to 100).toList.reduce(_*_)

它还给我 0。我不理解这种行为。如果 Int 已经溢出,它应该返回任何负数或正数。我很好奇,因此我尝试了这个:

(1 to 100).toList.fold(1)(_*_)

它仍然返回 0 然后我尝试了这个:

(1 to 100).toList.fold(1)((a,b) => { println(s"dd::::$a:::$b"); a*b })

它返回我:

scala> res0.toList.fold(1)((a,b) => { println(s"dd::::$a:::$b"); a*b })
dd::::1:::1
dd::::1:::2
dd::::2:::3
dd::::6:::4
dd::::24:::5
dd::::120:::6
dd::::720:::7
dd::::5040:::8
dd::::40320:::9
dd::::362880:::10
dd::::3628800:::11
dd::::39916800:::12
dd::::479001600:::13
dd::::1932053504:::14
dd::::1278945280:::15
dd::::2004310016:::16
dd::::2004189184:::17
dd::::-288522240:::18
dd::::-898433024:::19
dd::::109641728:::20
dd::::-2102132736:::21
dd::::-1195114496:::22
dd::::-522715136:::23
dd::::862453760:::24
dd::::-775946240:::25
dd::::2076180480:::26
dd::::-1853882368:::27
dd::::1484783616:::28
dd::::-1375731712:::29
dd::::-1241513984:::30
dd::::1409286144:::31
dd::::738197504:::32
dd::::-2147483648:::33
dd::::-2147483648:::34
dd::::0:::35
dd::::0:::36
dd::::0:::37
dd::::0:::38
dd::::0:::39
dd::::0:::40
dd::::0:::41
dd::::0:::42
dd::::0:::43
dd::::0:::44
dd::::0:::45
dd::::0:::46
dd::::0:::47
dd::::0:::48
dd::::0:::49
dd::::0:::50
dd::::0:::51
dd::::0:::52
dd::::0:::53
dd::::0:::54
dd::::0:::55
dd::::0:::56
dd::::0:::57
dd::::0:::58
dd::::0:::59
dd::::0:::60
dd::::0:::61
dd::::0:::62
dd::::0:::63
dd::::0:::64
dd::::0:::65
dd::::0:::66
dd::::0:::67
dd::::0:::68
dd::::0:::69
dd::::0:::70
dd::::0:::71
dd::::0:::72
dd::::0:::73
dd::::0:::74
dd::::0:::75
dd::::0:::76
dd::::0:::77
dd::::0:::78
dd::::0:::79
dd::::0:::80
dd::::0:::81
dd::::0:::82
dd::::0:::83
dd::::0:::84
dd::::0:::85
dd::::0:::86
dd::::0:::87
dd::::0:::88
dd::::0:::89
dd::::0:::90
dd::::0:::91
dd::::0:::92
dd::::0:::93
dd::::0:::94
dd::::0:::95
dd::::0:::96
dd::::0:::97
dd::::0:::98
dd::::0:::99
dd::::0:::100
res5: Int = 0

我不清楚这种行为。谁能帮忙!谢谢

【问题讨论】:

  • 整数溢出怎么办?
  • "如果 Int 已经溢出,它应该返回任何负数或正数。"为什么你认为它不能返回 0?

标签: java scala reduce scala-collections fold


【解决方案1】:

我不太清楚这种行为

通常,您遇到的是arithmetic overflow。如果您想准确找出第 34 个值返回 0 的原因,那么手动计算会有所帮助。

第33次乘积的结果是-2147483648,即:

64bit hex: 0x‭FFFFFFFF80000000‬
32bit hex: 0x80000000

64bit binary: ‭1111111111111111111111111111111110000000000000000000000000000000‬
32bit binary: 10000000000000000000000000000000

我们将它乘以 34,我们得到:

64bit hex: ‭0xFFFFFFEF00000000‬
32bit hex: 0x00000000‬

64bit binary: ‭1111111111111111111111111110111100000000000000000000000000000000‬
32bit binary: 00000000000000000000000000000000‬

由于Int 查看较低的 32 位,因此您得到 0。从这里开始的所有内容都将产生0,因为这是累加器的值,而你正在做乘法。

【讨论】:

    【解决方案2】:

    执行以下操作以了解发生了什么:

    val x = Int.MinValue
    x - 1 // = Int.MaxValue-1
    x + x // = 0
    x + x + x // = Int.MinValue
    

    当您从 Int.MinValue 中减去时,您从最大值开始。如果您从 MinValue (MinValue * 2) 中减去 abs(MinValue),您将执行从 MaxValue 剩下的 abs(MinValue) 步骤,这将使您变为 0。

    这种行为会导致 MinValue * 偶数 = 0 且 MinValue * 奇数 = MinValue 的情况

    这两种行为都发生在第 33-34 行,当然,只要你们中的一个结果为 0,那么所有其他结果也将为 0。

    【讨论】:

      【解决方案3】:

      在您的输出中有一行:dd::::-2147483648:::34,它产生0 作为输出。因此,所有后续的乘法结果都为0

      原因是-2147483648 的最小值为Int (Int.MinValue)。

      scala> Int.MinValue
      res6: Int = -2147483648
      

      如果你在 REPL 中尝试-2147483648 + -2147483648,由于Int 溢出,输出将是0。现在,当您执行-2147483648 * 34 时,它等同于(-2147483648 + (-2147483648)) * 17,因此输出为0

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-10-13
        • 2018-05-11
        • 2018-07-05
        • 2014-05-02
        • 1970-01-01
        • 2014-09-29
        • 2020-06-12
        • 2020-02-23
        相关资源
        最近更新 更多