2009-10-28 6 views
5

Su 2.7.5.final, sto cercando di aggiungere un elenco di Iterable Ints in questo modoScala: overflow nonostante l'uso di Long quando si aggiunge

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) 

Quando corro, ho

2147483647 
0 
4294967293 

E, si potrebbe dire "use reduceLeft (_ + _)", ma sembra essere in grado di restituire lo stesso tipo di elementi nell'elenco ... ma voglio accumularlo a Long, quindi non lo faccio t hanno problemi di overflow.

Aggiornamento 2009-10-28

Si tratta di un bug nella gamma, come sottolineato da Eastsun. È stato segnalato al team di Scala in ticket 2535

+0

Hmm, println (somma (Lista (Integer.MAX_VALUE - 1, Integer.MAX_VALUE))) produce 4294967293. Questo ha qualcosa a che fare con il metodo 'a' ho il sospetto. Domanda interessante! –

risposta

7

È un errore di gamma. C'è il codice sorgente del metodo foreach della 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 
    } 
} 

}

+0

Sembra che questo bug esista in Scala2.7.x e in Scala 2.8.x corrente. – Eastsun

+0

Qualcuno ha sollevato questo bug nella Scala Trac? –

+0

Non ancora (per quanto ne so) – Eastsun

5

s' Eastsun risposta ha dato una buona ragione per cui si calcolo overflow. Per risolvere il problema, ridefinire la funzione sum per utilizzare foldLeft, che consente di specificare l'accumulatore.

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

o utilizzando la scorciatoia per foldLeft (che mi piace molto come si mette il valore di partenza della piega di fronte alla Iterable si sta tentando di piegare).

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

In entrambi i casi, il codice che stavi cercando di eseguire dà i risultati corretti.

- Flaviu Cipcigan

Problemi correlati