Shivansh
Shivansh

Reputation: 3544

Scala reduce and fold returns 0 instead of a value

Hey I have a case where I tried to run this on REPL:

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

And it Returned me 0. I did not understand this behavior. If the Int has been overflowed it should have returned any negative or positive number. I got curious hence I tried this:

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

It still returned me 0 Then I tried this:

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

It returns me :

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

I do not understand this behavior clearly. Could anyone please help !Thanks

Upvotes: 1

Views: 264

Answers (3)

Yuval Itzchakov
Yuval Itzchakov

Reputation: 149538

I do not understand this behavior clearly

Generally, what you're experiencing is arithmetic overflow. If you want to pinpoint exactly why the 34th value returns 0, then doing the calculation by hand can help.

The result of the 33th product is -2147483648, which is:

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

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

We multiply it by 34, we get:

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

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

Since Int looks at the lower 32bit, you get 0. Everything on from here will result in 0 since that's the accumulators value and you're doing multiplication.

Upvotes: 5

justAbit
justAbit

Reputation: 4256

In your output there is one line like: dd::::-2147483648:::34, which produces 0 as output. Hence all subsequent multiplications result in 0.

Reason being -2147483648 in minimum value of Int (Int.MinValue).

scala> Int.MinValue
res6: Int = -2147483648

If you try -2147483648 + -2147483648 in REPL, because of Int overflow, output will be 0. Now when you do -2147483648 * 34 it is equivalent to (-2147483648 + (-2147483648)) * 17, hence output is 0.

Upvotes: 3

Michael Kopaniov
Michael Kopaniov

Reputation: 957

Execute the following to understand what is going on:

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

When you subtract from Int.MinValue you start from the max value. If you subtract abs(MinValue) from MinValue (MinValue * 2) you will be doing abs(MinValue) steps left from MaxValue which will bring you to 0.

This behaviour leads you to a situation in which MinValue * even number = 0 and MinValue * odd number = MinValue

Both behaviours occurred on lines 33-34, and of course as soon as one of you results is 0, all of your other results will be 0 as well.

Upvotes: 3

Related Questions