2009-10-28 15 views
5

を追加し、私は実行すると、私はスカラ:ロングの使用にもかかわらず、オーバーフロー2.7.5.finalで

2147483647 
0 
4294967293 
を取得するので、

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) 

のようにint型の反復処理可能なリストを追加しようとしています

そして、あなたは "reduceLeft(_ + _)"を使うかもしれませんが、リスト内の要素と同じ型しか返せないようです...しかし、私はLongに蓄積したいので、オーバーフローの問題があります。

更新2009-10-28

Eastsunで指摘したようにこれは、レンジのバグです。 Scalaチームに報告されましたticket 2535

+0

うーん、のprintln(合計(一覧(Integer.MAX_VALUEで - 1は、Integer.MAX_VALUE)))これは私が疑われる 'から' 法とは何かを持っている〜4294967293を生み出します。興味深い質問! –

答えて

7

これはRangeのバグです。 レンジのforeachのメソッドのソースコードがあります:

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

このバグはScala2.7.xと現在のScala 2.8.xに存在します。 – Eastsun

+0

誰かがScala Tracでこのバグを起こしましたか? –

+0

まだ(私が知る限り) – Eastsun

5

Eastsunの答えは、なぜあなたの計算がオーバーフロー非常に良い理由を与えました。回避策として、sum関数を再定義してfoldLeftを使用すると、アキュムレータを指定できます。 (それはIterableの前で倍の開始値を置くと、かなりのように、私はあなたがフォールドしようとしている)

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

またはfoldLeftの省略形を使用しました。

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

いずれの場合も、実行しようとしていたコードが正しい結果を返します。

- Flaviu Cipcigan

関連する問題