35 votes

Est-ce que 0.99999999999 peut être arrondi à 1.0 lors de la multiplication?

Lors de la multiplication d'un nombre à virgule flottante qui est très proche de 1, avec un int > 0, peut-il jamais être interprétée comme 1.

C'est, si Math.random() retourne son plus haut résultat possible (qui est l'étape 1 ci-dessous 1.0), sera

(int)(Math.random() * 8)

être 8 ou 7?

Pour un exemple pratique, cela peut-il souvent utilisé en construire de donner un indice en dehors des limites d'erreur:

someArray[(int)(Math.random() * someArray.length)];

Je suis particulièrement intéressé par les réponses pour Java et ActionScript 3, mais je suppose qu'ils utilisent tous les mêmes règles pour l'arithmétique à virgule flottante, et les réponses de la plate-forme serait utile.

Mise à jour: même Si j'ai déjà accepté une réponse, je serais encore apprécier la confirmation que cela ne peut pas aller de mal en ActionScript 3, puisqu'un collègue de rapports qu'il le voyait mal se passer une fois qu'est ce que la partie qui m'a poussé à poser cette question.

45voto

aioobe Points 158466

Si vous multipliez la plus grande valeur en dessous de 1.0 someInt (> 0), le résultat ne sera jamais someInt.

Cela peut être testés de manière exhaustive pour les entiers comme ceci:

Double greatestLessThanOne = Double.longBitsToDouble(4607182418800017407L);

// Assert that greatestLessThanOne is indeed the largest double less than 1.
//assert 1.0 == greatestLessThanOne + Math.ulp(greatestLessThanOne);

for (int i = 1; i >= 0; i++)
    if ((int) (greatestLessThanOne * i) == i)
        System.out.println("Exception found: " + i);

L'extrait de code ne produit aucune sortie.

(Math.ulp renvoie la distance entre le double et le double de la valeur à côté de plus grande ampleur. L'affirmation assure ainsi que greatestLessThanOne est en effet la plus grande valeur inférieure à 1,0.)

En d'autres termes, votre ligne

Object element = elementArray[(int)(Math.random() * elementArray.length)];

ne donnera jamais lieu à une ArrayIndexOutOfBoundsException.


En outre, selon la Marque Dickinsons commentaire sur ici, il en est de même lors de la multiplication par un double.

Avec la norme IEEE 754 arithmétique à virgule flottante en arrondi au plus proche de la mode, vous pouvez montrer que x * y < o pour n'importe quel x < 1.0 et non de minuscules positif y. (Il peut échouer si y est soit subnormale ou de la plus petite positive nombre normal.)

-2voto

hendra ong Points 21

Juste autour, ça peut être comme ça:

 BigDecimal bd = new BigDecimal(Double.toString(d));
bd = bd.setScale(decimalPlace,BigDecimal.ROUND_HALF_UP);
 

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X