9 Stimmen

Double um seine kleinste Schrittweite ändern

Ist etwas kaputt oder verstehe ich nicht, was passiert?

static String getRealBinary(double val) {
    long tmp = Double.doubleToLongBits(val);
    StringBuilder sb = new StringBuilder();

    for (long n = 64; --n > 0; tmp >>= 1)
        if ((tmp & 1) == 0)
            sb.insert(0, ('0'));
        else
            sb.insert(0, ('1'));

    sb.insert(0, '[').insert(2, "] [").insert(16, "] [").append(']');
    return sb.toString();
}

public static void main(String[] argv) {
    for (int j = 3; --j >= 0;) {
        double d = j;
        for (int i = 3; --i >= 0;) {
            d += Double.MIN_VALUE;
            System.out.println(d +getRealBinary(d));
        }
    }
}

Mit Ausgang:

2.0[1] [00000000000] [000000000000000000000000000000000000000000000000000]
2.0[1] [00000000000] [000000000000000000000000000000000000000000000000000]
2.0[1] [00000000000] [000000000000000000000000000000000000000000000000000]
1.0[0] [11111111110] [000000000000000000000000000000000000000000000000000]
1.0[0] [11111111110] [000000000000000000000000000000000000000000000000000]
1.0[0] [11111111110] [000000000000000000000000000000000000000000000000000]
4.9E-324[0] [00000000000] [000000000000000000000000000000000000000000000000001]
1.0E-323[0] [00000000000] [000000000000000000000000000000000000000000000000010]
1.5E-323[0] [00000000000] [000000000000000000000000000000000000000000000000011]

9voto

Marcelo Cantos Punkte 173498

Die allgemeine Idee ist, zunächst den Double in seine Long-Darstellung zu konvertieren (mit doubleToLongBits wie Sie es in getRealBinary ), erhöhen diesen Long um 1 und wandeln schließlich den neuen Long zurück in den Double, den er repräsentiert, mittels longBitsToDouble .

EDIT: Java (seit 1.5) bietet Math.ulp(double) , mit dem man vermutlich direkt den nächsthöheren Wert berechnen kann: x + Math.ulp(x) .

7voto

Mark Byers Punkte 761508

Fließkommazahlen sind nicht gleichmäßig über die Zahlenreihe verteilt, wie es bei Ganzzahlen der Fall ist. Sie sind in der Nähe von 0 dichter gepackt und liegen sehr weit auseinander, wenn man sich der Unendlichkeit nähert. Daher gibt es keine Konstante, die man zu einer Fließkommazahl addieren kann, um zur nächsten Fließkommazahl zu gelangen.

4voto

Ihr Code ist nicht wohlgeformt. Sie versuchen, den minimalen Double-Wert zu addieren und erwarten, dass sich das Ergebnis vom ursprünglichen Wert unterscheidet. Das Problem ist, dass double.MinValue so klein ist, dass das Ergebnis gerundet wird und nicht beeinflusst wird.

Empfohlene Lektüre: http://en.wikipedia.org/wiki/Machine_epsilon

In dem Wikipedia-Artikel ist auch der Java-Code enthalten. Epsilon ist per Definition die kleinste Zahl wie (X + eps * X != X), und eps*X wird "relatives Epsilon" genannt

4voto

Maciej Mikosik Punkte 365

Seit Java 1.8 gibt es java.lang.Math.nextUp(double) genau das tun, was Sie wollen. Es gibt auch das Gegenteil java.lang.Math.nextDown(double) .

0voto

Matthias Punkte 1058

Für den Fall, dass Sie die BigDecimal-Klasse verwenden möchten, gibt es die BigDecimal.ulp() Methode auch.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X