Scala: переполнение несмотря на использование Long при добавлении - PullRequest
5 голосов
/ 28 октября 2009

На 2.7.5.final я пытаюсь добавить итерируемый список Ints, например,

def sum(xs: Iterable[Int]): Long = {
  var sum = 0L
  xs.foreach((x) => sum = sum + x)
  sum
}

println(sum(List(1, Integer.MAX_VALUE - 1)))
println(sum(Integer.MAX_VALUE - 1 to Integer.MAX_VALUE))
println(0L + Integer.MAX_VALUE - 1 + Integer.MAX_VALUE)

Когда я бегу, я получаю

2147483647
0
4294967293

И вы могли бы сказать «использовать reduLeft (_ + _)», но кажется, что он может возвращать только тот же тип, что и элементы в списке ... но я хочу накапливать в Long, поэтому я не проблем с переполнением.

Обновление 2009-10-28

Это ошибка в Range, как указывает Eastsun. Об этом сообщается команде Scala в билете 2535

Ответы [ 2 ]

7 голосов
/ 28 октября 2009

Это ошибка Range. Вот исходный код метода foreach Range:

override def foreach(f: Int => Unit) {
if (step > 0) {
  var i = this.start
  *val until = if (inInterval(end)) end + 1 else end*      //bug here!!!

  while (i < until) {
    f(i)
    i += step
  }
} else {
  var i = this.start
  val until = if (inInterval(end)) end - 1 else end

  while (i > until) {
    f(i)
    i += step
  }
}

}

5 голосов
/ 28 октября 2009

Ответ Eastsun дал очень вескую причину, по которой вы вычислили переполнения. В качестве обходного пути я бы переопределил функцию sum для использования foldLeft, которая позволяет вам указать аккумулятор.

def sum(xs: Iterable[Int]): Long =
  xs.foldLeft(0L)(_ + _)

или использование сокращения для foldLeft (что мне очень нравится, поскольку оно ставит начальное значение сгиба перед Iterable, который вы пытаетесь сбросить).

def sum(xs: Iterable[Int]): Long =
  (0L /: xs)(_ + _)

В обоих случаях код, который вы пытались запустить, дает правильные результаты.

- Флавиу Чипчиган

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...