Maison >Java >javaDidacticiel >Pourquoi la double perd la précision et comment l'éviter à Java
Lorsque vous travaillez avec des nombres à virgule flottante en Java, vous remarquerez peut-être que double produit parfois des résultats inattendus ou imprécis. Ce comportement peut conduire à des erreurs, en particulier dans les applications ou scénarios financiers qui nécessitent une grande précision.
Dans cet article, nous examinerons la cause profonde de ce problème, expliquerons comment l'éviter, fournirons un exemple concret et explorerons si les versions Java plus récentes offrent de meilleures alternatives.
Le type de données double en Java suit la norme de fonctionnement des nombres à virgule flottante IEEE 754. Il représente les nombres au format binaire en utilisant :
Cette représentation binaire introduit des limitations :
Par exemple, en binaire :
Les opérations impliquant un double peuvent accumuler des erreurs :
Ce comportement est inhérent à l'arithmétique à virgule flottante et n'est pas propre à Java.
Voici un exemple illustrant le problème :
<code class="language-java">public class DoublePrecisionLoss { public static void main(String[] args) { double num1 = 0.1; double num2 = 0.2; double sum = num1 + num2; System.out.println("预期和:0.3"); System.out.println("实际和:" + sum); // 比较 if (sum == 0.3) { System.out.println("和等于0.3"); } else { System.out.println("和不等于0.3"); } } }</code>
Sortie :
<code>预期和:0.3 实际和:0.30000000000000004 和不等于0.3</code>
Le résultat 0,30000000000000004 met en évidence l'erreur d'arrondi provoquée par la représentation binaire. Même des différences insignifiantes peuvent entraîner des problèmes majeurs dans les systèmes critiques.
La classe BigDecimal en Java fournit une arithmétique de précision arbitraire, ce qui la rend idéale pour les scénarios nécessitant une haute précision (tels que les calculs financiers).
<code class="language-java">import java.math.BigDecimal; public class BigDecimalExample { public static void main(String[] args) { BigDecimal num1 = new BigDecimal("0.1"); BigDecimal num2 = new BigDecimal("0.2"); BigDecimal sum = num1.add(num2); System.out.println("预期和:0.3"); System.out.println("实际和:" + sum); // 比较 if (sum.compareTo(new BigDecimal("0.3")) == 0) { System.out.println("和等于0.3"); } else { System.out.println("和不等于0.3"); } } }</code>
Sortie :
<code>预期和:0.3 实际和:0.3 和等于0.3</code>
En utilisant BigDecimal, les problèmes de précision sont éliminés et les comparaisons produisent des résultats corrects.
Une autre façon de gérer la perte de précision est de comparer les nombres à virgule flottante avec une tolérance (epsilon). Cette méthode vérifie si les nombres sont « suffisamment proches » plutôt que de s’appuyer sur une égalité exacte.
<code class="language-java">public class EpsilonComparison { public static void main(String[] args) { double num1 = 0.1; double num2 = 0.2; double sum = num1 + num2; double epsilon = 1e-9; // 定义一个小的容差值 System.out.println("预期和:0.3"); System.out.println("实际和:" + sum); // 使用epsilon进行比较 if (Math.abs(sum - 0.3) < epsilon) { System.out.println("和大约等于0.3"); } else { System.out.println("和不等于0.3"); } } }</code>
Sortie :
<code class="language-java">public class DoublePrecisionLoss { public static void main(String[] args) { double num1 = 0.1; double num2 = 0.2; double sum = num1 + num2; System.out.println("预期和:0.3"); System.out.println("实际和:" + sum); // 比较 if (sum == 0.3) { System.out.println("和等于0.3"); } else { System.out.println("和不等于0.3"); } } }</code>
Exemple: utilisez la précision.equals pour comparer
<code>预期和:0.3 实际和:0.30000000000000004 和不等于0.3</code>
Pourquoi utiliser les mathématiques Apache Commons?
<code class="language-java">import java.math.BigDecimal; public class BigDecimalExample { public static void main(String[] args) { BigDecimal num1 = new BigDecimal("0.1"); BigDecimal num2 = new BigDecimal("0.2"); BigDecimal sum = num1.add(num2); System.out.println("预期和:0.3"); System.out.println("实际和:" + sum); // 比较 if (sum.compareTo(new BigDecimal("0.3")) == 0) { System.out.println("和等于0.3"); } else { System.out.println("和不等于0.3"); } } }</code>
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!