2016-07-18 9 views
1

Эй у меня есть случай, когда я попытался запустить это на РЕПЛ:Scala сократить и сложите возвращает 0 вместо значения

(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 

Я не понимаю такого поведения ясно. Может кто-нибудь, пожалуйста, помогите спасибо

+0

Что касается переполнения целого числа? –

+0

«Если Int был переполнен, он должен был вернуть любое отрицательное или положительное число». Почему вы думаете, что он не может вернуться 0? –

ответ

5

Я не понимаю, такое поведение явно

Вообще, то, что вы испытываете, 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, так как это значение аккумулятора, и вы делаете умножение.

+0

Спасибо @yuval, объяснив это мне :) –

+0

@ShivanshSrivastava Вы приветствуете :) Надеюсь, что это объясняет. –

3

Выполните следующие действия, чтобы понять, что происходит:

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

При вычитании из Int.MinValue отталкиваться от максимального значения. Если вы вычтите abs (MinValue) из MinValue (MinValue * 2), вы будете делать абс (MinValue) шаги, оставшиеся от MaxValue, которые приведут вас к 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 

Если вы пытаетесь -2147483648 + -2147483648 в РЕПЛ, из-за переполнения Int, выход будет 0. Теперь, когда вы делаете -2147483648 * 34, это эквивалентно (-2147483648 + (-2147483648)) * 17, поэтому выход - 0.