Comment obtenir la partie décimale d’un flotteur?

J’ai besoin d’extraire la partie décimale d’un nombre flottant, mais j’obtiens des résultats étranges:

float n = 22.65f; // I want x = 0.65f, but... x = n % 1; // x = 0.6499996 x = n - Math.floor(n); // x = 0.6499996185302734 x = n - (int)n; // x = 0.6499996 

Pourquoi cela arrive-t-il? Pourquoi est-ce que je reçois ces valeurs au lieu de 0.65 ?

float ne dispose que de quelques chiffres de précision, vous devriez donc vous attendre à voir une erreur de ronde assez facilement. essayez de double cela a plus de précision mais a toujours des erreurs d’arrondi. Vous devez arrondir toutes les réponses que vous obtenez pour avoir une sortie saine.

Si ce n’est pas souhaitable, vous pouvez utiliser BigDecimal qui n’a pas d’erreurs d’arrondi, mais qui a ses propres problèmes.

EDIT: Vous pouvez trouver cela intéressant. La valeur par défaut Float.toSsortingng () utilise un arrondi minimal, mais souvent cela ne suffit pas.

 System.out.println("With no rounding"); float n = 22.65f; System.out.println("n= "+new BigDecimal(n)); float expected = 0.65f; System.out.println("expected= "+new BigDecimal(expected)); System.out.println("n % 1= "+new BigDecimal(n % 1)); System.out.println("n - Math.floor(n) = "+new BigDecimal(n - Math.floor(n))); System.out.println("n - (int)n= "+new BigDecimal(n - (int)n)); System.out.println("With rounding"); System.out.printf("n %% 1= %.2f%n", n % 1); System.out.printf("n - Math.floor(n) = %.2f%n", n - Math.floor(n)); System.out.printf("n - (int)n= %.2f%n", n - (int)n); 

Des tirages

 With no rounding n= 22.6499996185302734375 expected= 0.64999997615814208984375 n % 1= 0.6499996185302734375 n - Math.floor(n) = 0.6499996185302734375 n - (int)n= 0.6499996185302734375 With rounding n % 1= 0.65 n - Math.floor(n) = 0.65 n - (int)n= 0.65 

Je pense que ce serait le moyen le plus simple:

 float n = 22.65f; float x = n - (int) n; 

Parce que tous les nombres rationnels ne peuvent pas être représentés par un nombre à virgule flottante et que 0.6499996... est l’approximation la plus proche pour 0.65 .

Par exemple, essayez d’imprimer les 20 premiers chiffres du nombre 0.65 :

  System.out.printf("%.20f\n", 0.65f); 

->

  0.64999997615814210000 

modifier
Les erreurs d’arrondi, qui s’accumulent lors des calculs, y jouent également un rôle, comme d’autres l’ont noté.

Je mordis un peu mais travaille:

 BigDecimal.valueOf(2.65d).divideAndRemainder(BigDecimal.ONE)[1].floatValue() 

Si vous voulez simplement imprimer le nombre à 2dp, vous pouvez utiliser DecimalFormat.

 DecimalFormat df= new DecimalFormat("#.##"); System.out.println(df.format(f)); 

Si vous voulez des nombres à virgule fixe en interne, utilisez BigDecimal

Réponse courte: Vous ne pouvez pas représenter certains nombres exactement en binary qui sont “exacts” en décimal.

Réponse longue: http://www-users.math.umd.edu/~jkolesar/mait613/floating_point_math.pdf

[Modifier]

Aussi une lecture intéressante: http://www.cs.berkeley.edu/~wkahan/JAVAhurt.pdf

La méthode sonore et parfaite pour obtenir la partie décimale des types de données float et double utilise avec Ssortingng comme ce code:

 float num=2.35f; Ssortingng s= new Float(num).toSsortingng(); Ssortingng p=s.subssortingng(s.indexOf('.')+1,s.length()); int decimal=Integer.parseInt(p); 

Essaye ça. Si le temporisateur est 10,65, alors h se termine par les deux premières décimales * 100 = 65.

C’est un moyen rapide et facile de séparer ce que vous voulez sans les problèmes d’arrondi.

 float h = (int)((timer % 1) * 100); 

Essayez java.math.BigDecimal .

Ce code fonctionnera pour n’importe quel nombre de chiffres décimaux.

 float f = 2.3445f; Ssortingng s = Float.toSsortingng(f); char[] c = s.toCharArray(); int length = s.length(); int flag = 0; SsortingngBuilder n = new SsortingngBuilder(); for(int i = 0; i < length; i++) { if(flag == 1) { n.append(c[i]); } if(c[i] == '.') { flag = 1; } } String result = n.toString(); int answer = Integer.parseInt(result); System.out.println(answer);