2016-05-24 11 views
1

Ich möchte prüfen, ob das Hinzufügen eines Wertes zu einem doppelten Wert die doppelten Grenzen überschreitet oder nicht. Ich versuchte dies:Scala: Wie überprüft man, ob ein Double Value Crossing Double limits?

object Hello { 
    def main(args: Array[String]): Unit = { 
    var t = Double.MaxValue 
    var t2 = t+100000000 
    if(t2 > 0) { 
     println("t2 > 0: " + t2) 
    } else 
     println("t2 <= 0: " + t2) 
    } 

} 

Der Ausgang ich erhalte, ist

t2 > 0: 1.7976931348623157E308 

Was ich will, ist eigentlich Milliarden von Werten zu summieren und prüfen Sie, ob die laufende Summe jederzeit überläuft.

+0

Können Sie den ** ersten Wert ** von Double.MaxValue subtrahieren und prüfen, ob dieser größer als ** zweiter Wert ** ist? – arpanchaudhury

Antwort

3

Der erste Teil Ihrer Frage scheint von einem Missverständnis der Fließkommazahlen zu stammen.

  1. IEEE-754 Gleitkommazahlen sind nicht wie einige endliche Ganzzahlen umlaufen. Stattdessen "sättigen" sie bei Double.PositiveInfinity, die mathematische Unendlichkeit darstellt. Double.MaxValue ist der größte endliche positive Wert von Doppelpunkten. Die nächste ist danach Double.PositiveInfinity. Das Hinzufügen eines anderen als Double.NegativeInfinity und NaN s zu Double.PositiveInfinity ergibt Double.PositiveInfinity.

    scala> Double.PositiveInfinity + 1 
    res0: Double = Infinity 
    
    scala> Double.PositiveInfinity - 1 
    res1: Double = Infinity 
    
    scala> Double.PositiveInfinity + Double.NaN 
    res2: Double = NaN 
    
    scala> Double.PositiveInfinity + Double.NegativeInfinity 
    res3: Double = NaN 
    
  2. Gleitkommazahlen werden mit zunehmender Größe kleiner und weiter voneinander entfernt. Double.MaxValue + 100000000 wertet Double.MaxValue als Ergebnis des Abrundungsfehlers aus: Double.MaxValue ist so viel größer als 100000000, dass der ehemalige "schluckt" letzteres, wenn Sie versuchen, sie hinzuzufügen. Sie müssten eine Double in der Größenordnung von math.pow(2, -52) * Double.MaxValue-Double.MaxValue hinzuzufügen, um Double.PositiveInfinity zu erhalten:

    scala> math.pow(2,-52) * Double.MaxValue + Double.MaxValue 
    res4: Double = Infinity 
    

Jetzt schreiben Sie

What I actually want is to sum billions of values and check whether or not the running sum overflows at any time.

Ein möglicher Ansatz ist zu definieren, eine Funktion, die die Zahlen rekursiv hinzufügt, aber anhält, wenn die laufende Summe eine Unendlichkeit oder NaN ist, und das Ergebnis in eineumschließt:

import scala.collection.immutable 

def sumToEither(xs: immutable.Seq[Double]): Either[String, Double] = { 
    @annotation.tailrec 
    def go(ys: immutable.Seq[Double], acc: Double): Double = 
    if (ys.isEmpty || acc.isInfinite || acc.isNaN) acc 
    else go(ys.tail, ys.head + acc) 
    go(xs, 0.0) match { 
    case x if x.isInfinite => Left("overflow") 
    case x if x.isNaN => Left("NaN") 
    case x => Right(x) 
    } 
} 
+0

Eigentlich möchte ich die Summe von Milliarden von Werten erhalten und überprüfen, ob die Summe jederzeit überläuft oder nicht. Könntest du bitte einen Weg finden, das zu überprüfen? –

2

Als Antwort auf Ihre Frage in den Kommentaren:

Actually, I want to get the total of billions of values and check if the total overflows anytime or not. Could you please tell a way to check that?

Wenn die Gesamtüberläuft, wird das Ergebnis entweder eine unendlich (entweder positiv oder negativ) oder NaN (wenn an einigen Punkt, den Sie eine positive und negative Unendlichkeit hinzugefügt haben): der einfachste Weg ist zu überprüfen total.isInfinity || total.isNaN.

+0

Ich habe meine Antwort aktualisiert, als du deine gepostet hast :) – Jubobs