Quel est le meilleur moyen de convertir un double en long sans casting?
Par exemple:
double d = 394.000;
long l = (new Double(d)).longValue();
System.out.println("double=" + d + ", long=" + l);
En supposant que vous soyez satisfait de tronquer vers zéro, lancez simplement:
double d = 1234.56;
long x = (long) d; // x = 1234
Ce sera plus rapide que de passer par les classes wrapper - et plus important encore, c'est plus lisible. Maintenant, si vous avez besoin d'arrondi autre que "toujours vers zéro", vous aurez besoin d'un code légèrement plus compliqué.
... Et voici la manière d'arrondir qui ne tronque pas. Dépêchez-vous de chercher dans le manuel de l'API Java:
double d = 1234.56;
long x = Math.round(d);
L'approche privilégiée devrait être:
Double.valueOf(d).longValue()
A partir de la documentation Double (Java Platform SE 7) :
Double.valueOf(d)
Renvoie une instance
Double
représentant la valeurdouble
spécifiée . Si une nouvelle instanceDouble
n'est pas requise, cette méthode devrait généralement être utilisé de préférence au constructeurDouble(double)
, comme cette méthode est susceptible de donner beaucoup mieux l'espace et le temps performances en mettant en cache les valeurs fréquemment demandées.
(new Double(d)).longValue()
fait en interne une distribution, il n'y a donc aucune raison de créer un objet Double.
La bibliothèque Guava Math a une méthode spécialement conçue pour convertir un double en un long:
long DoubleMath.roundToLong(double x, RoundingMode mode)
Vous pouvez utiliser Java.math.RoundingMode
pour spécifier le comportement d'arrondi.
Si vous soupçonnez fort que le DOUBLE est en réalité un LONG, et que vous voulez
1) avoir une idée de sa valeur exacte en tant que LONG
2) jeter une erreur quand ce n'est pas un long
vous pouvez essayer quelque chose comme ceci:
public class NumberUtils {
/**
* Convert a {@link Double} to a {@link Long}.
* Method is for {@link Double}s that are actually {@link Long}s and we just
* want to get a handle on it as one.
*/
public static long getDoubleAsLong(double specifiedNumber) {
Assert.isTrue(NumberUtils.isWhole(specifiedNumber));
Assert.isTrue(specifiedNumber <= Long.MAX_VALUE && specifiedNumber >= Long.MIN_VALUE);
// we already know its whole and in the Long range
return Double.valueOf(specifiedNumber).longValue();
}
public static boolean isWhole(double specifiedNumber) {
// http://stackoverflow.com/questions/15963895/how-to-check-if-a-double-value-has-no-decimal-part
return (specifiedNumber % 1 == 0);
}
}
Long est un sous-ensemble de Double, vous pouvez donc obtenir des résultats étranges si vous essayez inconsciemment de convertir un Double qui est en dehors de la plage de Long:
@Test
public void test() throws Exception {
// Confirm that LONG is a subset of DOUBLE, so numbers outside of the range can be problematic
Assert.isTrue(Long.MAX_VALUE < Double.MAX_VALUE);
Assert.isTrue(Long.MIN_VALUE > -Double.MAX_VALUE); // Not Double.MIN_VALUE => read the Javadocs, Double.MIN_VALUE is the smallest POSITIVE double, not the bottom of the range of values that Double can possible be
// Double.longValue() failure due to being out of range => results are the same even though I minus ten
System.out.println("Double.valueOf(Double.MAX_VALUE).longValue(): " + Double.valueOf(Double.MAX_VALUE).longValue());
System.out.println("Double.valueOf(Double.MAX_VALUE - 10).longValue(): " + Double.valueOf(Double.MAX_VALUE - 10).longValue());
// casting failure due to being out of range => results are the same even though I minus ten
System.out.println("(long) Double.valueOf(Double.MAX_VALUE): " + (long) Double.valueOf(Double.MAX_VALUE).doubleValue());
System.out.println("(long) Double.valueOf(Double.MAX_VALUE - 10).longValue(): " + (long) Double.valueOf(Double.MAX_VALUE - 10).doubleValue());
}
Voulez-vous avoir une conversion binaire comme
double result = Double.longBitsToDouble(394.000d);
En termes simples, le casting est plus efficace que la création d'un objet Double.
Simplement par ce qui suit:
double d = 394.000;
long l = d * 1L;