Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Scala: overflow despite use of Long when adding

Tags:

scala

On 2.7.5.final, I'm attempting to add a Iterable list of Ints like so

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)

When I run, I get

2147483647
0
4294967293

And, you might say "use reduceLeft(_ + _)", but it seems to only be able to return the same type as elements in the list... but I want to accumulate to a Long, so I don't have overflow issues.

Update 2009-10-28

This is a bug in Range, as pointed out by Eastsun. It's been reported to the Scala team in ticket 2535

like image 616
Trenton Avatar asked Oct 28 '09 03:10

Trenton


People also ask

What happens if we assign an integer value to a variable that is too large for that variable to hold in java?

The value is too big for an int or double variable in Java, and there will be an overflow.

How do you deal with int overflow?

In languages where integer overflow can occur, you can reduce its likelihood by using larger integer types, like Java's long or C's long long int. If you need to store something even bigger, there are libraries built to handle arbitrarily large numbers.

What happens when unsigned int overflows?

"A computation involving unsigned operands can never overflow, because a result that cannot be represented by the resulting unsigned integer type is reduced modulo the number that is one greater than the largest value that can be represented by the resulting type."

What happens when integer overflows?

An integer overflow occurs when you attempt to store inside an integer variable a value that is larger than the maximum value the variable can hold. The C standard defines this situation as undefined behavior (meaning that anything might happen).


1 Answers

It's a bug of Range. There is the source code of Range's foreach method:

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
  }
}

}

like image 85
Eastsun Avatar answered Sep 30 '22 13:09

Eastsun