web-dev-qa-db-fra.com

Comment déterminer la précision maximale pour double

J'essaie de déterminer quelle est la précision maximale d'un double. Dans les commentaires pour la réponse acceptée dans ce lien Conserver la précision avec double en Java @PeterLawrey indique la précision maximale dans 15.

Comment déterminez-vous cela?

13
Shivam Sinha

@PeterLawrey indique la précision maximale sur 15.

Ce n'est pas ce qu'il a déclaré du tout. Ce qu'il a déclaré était:

double a 15 décimales de précision

et il a tort. Ils ont 15 décimales chiffres de précision.

Le nombre de chiffres décimaux dans n'importe quel nombre est donné par son journal à la base 10. 15 est la valeur plancher de journaldix(253-1), où 53 est le nombre de bits de la mantisse (y compris le bit impliqué), comme décrit dans Javadoc et IEEE 754, et 253-1 est donc la valeur maximale possible de la mantisse. La valeur réelle est de 15,95458979719191003298111788092734 jusqu'aux limites de la calculatrice Windows. 

Il a tout à fait tort de le décrire comme "des décimales de précision". Une double a 15 décimales chiffres de précision si elles sont toutes avant la virgule décimale. Pour les nombres avec des fractions, vous pouvez avoir plus de 15 chiffres dans la représentation décimale, à cause de l'incommensurabilité des fractions décimales et binaires. 

9
user207421

Vous pouvez aussi "le mesurer" directement: 

for(double d = 1 ; d > 0 ; d/=2) System.out.println(d);

L'idée de ce code est d'atteindre le plus petit nombre avec un seul bit. Donc, vous commencez avec 1 (qui n'a qu'un bit) et divisez par deux (ce qui décale les bits vers la droite en binaire) jusqu'au dernier bit. Le dernier numéro imprimé par cette boucle est: 

4.9E-324

0
Maljam

Exécutez ce code et voyez où il s'arrête

public class FindPrecisionDouble {
  static public void main(String[] args) {
    double x = 1.0;
    double y = 0.5;
    double epsilon = 0;
    int nb_iter = 0;
    while ((nb_iter < 1000) && (x != y)) {
        System.out.println(x-y);
        epsilon = Math.abs(x-y);
        y = ( x + y ) * 0.5;
    }
    final double prec_decimal = - Math.log(epsilon) / Math.log(10.0);
    final double prec_binary = - Math.log(epsilon) / Math.log(2.0);
    System.out.print("On this machine, for the 'double' type, ");
    System.out.print("epsilon = " );
    System.out.println( epsilon );
    System.out.print("The decimal precision is " );
    System.out.print( prec_decimal );
    System.out.println(" digits" );
    System.out.print("The binary precision is " );
    System.out.print( prec_binary );
    System.out.println(" bits" );
  }
}

La variable y devient la plus petite valeur différente de 1.0. Sur mon ordinateur (Mac Intel Core i5), il s’arrête à 1.1102...E-16. Il imprime ensuite la précision (en décimal et en binaire).

Comme indiqué dans https://en.wikipedia.org/wiki/Machine_epsilon , la précision en virgule flottante peut être estimée avec la valeur epsilon . Il s'agit du "plus petit nombre qui, ajouté à un, donne un résultat différent de un "(j'ai fait une petite variation: 1-e au lieu de 1 + e, mais la logique est la même)

Je vais expliquer en décimal: si vous avez une précision de 4 décimales, vous pouvez exprimer 1.0000 - 0.0001, mais vous ne pouvez pas exprimer le nombre 1.00000-0.00001 (il vous manque la 5ème décimale). Dans cet exemple, avec une précision de 4 décimales, le epsilon est 0,0001. Epsilon mesure directement la précision en virgule flottante. Il suffit de transposer en binaire. 

Modifier Votre question demandait "Comment déterminer ...". La réponse que vous cherchiez était plus une explication qu'une manière de déterminer la précision (avec la réponse que vous avez acceptée). Quoi qu'il en soit, pour d’autres personnes, l’exécution de ce code sur une machine déterminera la précision du type "double".

0
Sci Prog