2016-10-21 5 views
2

Ich habe Werte zwischen 0 und 1 als Floats gespeichert. Ich weiß, dass das Delta zwischen unterscheidbaren Floats kleiner ist, je näher die Floats bei 0 liegen. Daher denke ich, dass die Präzision in meinem Fall sehr hoch ist (da der höchstmögliche Float 1 ... ist). Wie groß ist mein epsilon, das ich berücksichtigen muss, wenn ich 2 dieser Schwimmer vergleiche? wie groß ist die Lücke zwischen 1.0f und dem größten darstellbaren Float, der kleiner als 1.0f ist? Es tut mir leid, wenn diese Frage zu breit scheint/General, aber ich konnte keine Antwort finden :-(. DankJava Float Precision für Werte zwischen 0 und 1

Antwort

7

Sie die Funktion nutzen können java.lang.Math.nextAfter(float start, double direction) Ihnen zu helfen.

Rufen Sie es, in Ihrem Fall, nextAfter(1.0f, 0.0). Hier sind wir die direction Einstellung Startnummer auf weniger als, so wird es „rückwärts“ suchen. die resultierende float ist Ihre Antwort.

Da diese Funktion auch eine Überlastung taking a double für start hat, sein vorsichtig verwenden 1.0f, um eine float lit eral.

+1

Bei Verwendung von 1.8 oder höher, 'java.lang.Math.nextDown (1.0f) 'oder, wenn man die normalerweise bessere Wahl von' double' anstelle von 'float' verwendet,' java.lang. Math.nextDown (1.0) ' –

+0

Ich weiß Double wäre besser, aber ich habe keinen Speicher mehr, also möchte ich herausfinden, ob float für meine Zwecke ausreicht. Anyway, danke für den Kommentar, denn Java 1.8 verwenden und damit die jeweilige Funktion nutzen können. – schubakah

1

Um die Einheit der Auflösung für einen Float- oder Double-Wert zu erhalten, können Sie Math.ulp(x) verwenden, was Ihnen den Unterschied zwischen x und dem nächsten darstellbaren Wert gibt. Hinweis: 1 hat die doppelte Lücke des Wertes unmittelbar vor 1,0

float f = 1.0f, f_1 = Math.nextDown(f); 
double d = 1.0, d_1 = Math.nextDown(d); 

int f_1i = Float.floatToRawIntBits(f_1); 
System.out.println("f_1=" + f_1 + " f_1i=" + Integer.toHexString(f_1i) + " eps=" + Math.ulp(f_1) + " nextUp=" + Math.nextUp(f_1)); 

int fi = Float.floatToRawIntBits(f); 
System.out.println("f=" + f + " fi=" + Integer.toHexString(fi) + " eps=" + Math.ulp(f) + " nextUp=" + Math.nextUp(f)); 

long d_1i = Double.doubleToRawLongBits(d_1); 
System.out.println("d_1=" + d_1 + " d_1i=" + Long.toHexString(d_1i) + " eps=" + Math.ulp(d_1) + " nextUp=" + Math.nextUp(d_1)); 

long di = Double.doubleToRawLongBits(d); 
System.out.println("d=" + d + " di=" + Long.toHexString(di) + " eps=" + Math.ulp(d) + " nextUp=" + Math.nextUp(d)); 

druckt

f_1=0.99999994 f_1i=3f7fffff eps=5.9604645E-8 nextUp=1.0 
f=1.0 fi=3f800000 eps=1.1920929E-7 nextUp=1.0000001 
d_1=0.9999999999999999 d_1i=3fefffffffffffff eps=1.1102230246251565E-16 nextUp=1.0 
d=1.0 di=3ff0000000000000 eps=2.220446049250313E-16 nextUp=1.0000000000000002 

Sie können auch tun Arithmetik auf den darstellbaren Werte bei den rohen ganzzahligen Darstellungen suchen.

z.B. Math.nextUp

public static double nextUp(double d) { 
    if(Double.isNaN(d) || d == Double.POSITIVE_INFINITY) 
     return d; 
    else { 
     d += 0.0d; 
     return Double.longBitsToDouble(Double.doubleToRawLongBits(d) + 
             ((d >= 0.0d)?+1L:-1L)); 
    } 
} 

BTW d += 0.0d dreht -0.0 in +0.0

Auch

System.out.println(Math.ulp(Double.NEGATIVE_INFINITY)); 

druckt

Infinity 
+1

Eigentlich ist das eine gute Antwort. Upvoted. – Bathsheba

+1

@Bathsheba hehe, du scheinst so überrascht zu sein. ;) –