Problème pour obtenir des chiffres dans une double variable
-
13-11-2019 - |
Question
J'ai eu un petit problème avec une fonction dont j'ai besoin dans mon progam Java. Je veux vérifier la quantité totale de chiffres, une variable «double» a. (Par exemple: 5 devrait retourner 1, 5.0034 devrait retourner 5 et 2.04 devrait retourner 3.) Ma fonction est la suivante:
private int getDoubleLength (double a) {
int len = 0;
while (a != (int) a) {
a *= 10;
}
while (a > 1) {
len ++;
a/=10;
}
System.out.println(String.format("Double %f has %d digits.",a,len));
return len;
}
Maintenant, cela fonctionne parfaitement, mais lorsque je fais des calculs mathématiques, vous obtenez les légères erreurs de double: je divise 10 par cos (60), qui est 0,5. La réponse doit être de 20,0, mais le programme donne un 20.000000000000004 (ce numéro, je l'ai copié). Ma boucle while est coincée et le programme est suspendu.
Des idées? (Ou d'autres excellentes solutions pour vérifier les chiffres d'un nombre!)
La solution
Les doubles et les flotteurs et les opérations ne sont donc pas exacts, il y aura donc toujours de légères erreurs par rapport aux calculs algébriques. Si vous utilisez des cosinus, etc., vous devrez toujours faire face à ces erreurs d'arrondi que tout livre ou texte Web sur l'analyse numérique devrait décrire. Si vous utilisez des opérations aritmétiques simples, regardez java.lang.bigdecimal
Pour plus de détails sur la façon dont les valeurs de points flottantes sont stockées. Ce que chaque informaticien doit savoir sur l'arithmétique à virgule flottante
Autres conseils
toString (). la longueur () devrait le résoudre
rappelez-vous pour soustraire le «». S'il est là et ne devrait pas être compté
C'est ainsi que j'ai implémenté le mien, une simple conversion en chaîne lorsque le double était en grande chaîne retournée avec une représentation exponentielle. IE 20000000 retournerait 2.0e + 7, et la scission la diviserait ensuite à partir d'ici, ce qui entraînerait un mauvais nombre. J'avais l'habitude de BigDecimal
et à toPlainString()
méthode
protected int countDecimalDigits(Double d) {
BigDecimal deci = BigDecimal.valueOf(d);
int integerPlaces = 0;
int decimalPlaces = 0;
String text = deci.toPlainString();
String[] integerDecimalSplit = text.split("\\.");
if (null != integerDecimalSplit[0]) {
integerPlaces = integerDecimalSplit[0].length();
}
if (integerDecimalSplit.length > 1) {
decimalPlaces = integerDecimalSplit[1].length();
}
return integerPlaces + decimalPlaces;
}
C'est un problème d'arrondi. J'utiliserais des chaînes, compterais les caractères et déciderais de ce que les chiffres doivent être comptés significatifs.