web-dev-qa-db-fra.com

Division simple en Java - s'agit-il d'un bogue ou d'une fonctionnalité?

J'essaie ce calcul simple dans une application Java:

System.out.println("b=" + (1 - 7/10));

Évidemment, je veux b=0.3 pour la sortie, mais voici ce que je reçois b=1.

Quoi?! Pourquoi cela se produit-il?

Si je fais:

System.out.println("b=" + (1 - 0.7));

Je reçois le bon résultat qui est b=0.3.

Qu'est-ce qui ne va pas ici?

18
msr

Vous utilisez la division entière.

Essayez 7.0/10 à la place.

57
Xavier Ho

Vous avez utilisé des nombres entiers dans l'expression 7/10 et le nombre entier 7 divisé par le nombre entier 10 est égal à zéro.

Ce que vous attendez est une division en virgule flottante. N'importe lequel des éléments suivants évaluerait la façon dont vous vous attendiez:

7.0 / 10
7 / 10.0
7.0 / 10.0
7 / (double) 10
24
JustJeff

S'il vous plaît ne prenez pas cela comme une réponse à la question. Ce n'est pas, mais un conseil lié à l'exploitation de la différence d'int et float. J'aurais mis cela sous un commentaire sauf que la zone de réponse me permet de formater ce commentaire.

Cette fonctionnalité est utilisée dans tous les langages de programmation respectables depuis l'époque de fortran (ou antérieure) - je dois avouer que j'ai déjà été programmeur de cartes perforées Fortran et Cobol.

À titre d’exemple, une division entière de 10/3 donne une valeur entière 3, puisqu’un entier n’a aucune possibilité de conserver une fraction résiduelle .3333 ...

Le contrôle de boucle est l'un des moyens utilisés par nous (les programmeurs anciens) pour utiliser cette fonctionnalité.

Supposons que nous souhaitons imprimer un tableau de 1000 chaînes, mais que nous souhaitions insérer un saut de ligne toutes les 15 chaînes, pour insérer de jolis caractères à la fin de la ligne et au début de la ligne suivante. Nous l'exploitons, étant donné que l'entier k est la position d'une chaîne dans ce tableau.

int(k/15)*15 == k

n'est vrai que lorsque k est divisible par 15, une occurrence à une fréquence de 15 cellules. Ce qui s'apparente à ce que mon ami a dit à propos de la montre morte de son grand-père étant exacte deux fois par jour.

int(1/15) = 0 -> int(1/15)*15 = 0
int(2/15) = 0 -> int(2/15)*15 = 0
...
int(14/15) = 0 -> int(14/15)*15 = 0
int(15/15) = 1 -> int(15/15)*15 = 15

int(16/15) = 1 -> int(16/15)*15 = 15
int(17/15) = 1 -> int(17/15)*15 = 15
...
int(29/15) = 1 -> int(29/15)*15 = 15
int(30/15) = 2 -> int(30/15)*15 = 30

Par conséquent, la boucle,

leftPrettyfy();
for(int k=0; k<sa.length; k++){
  print(sa[k]);
  int z = k + 1;
  if ((z/15)*15 == z){
    rightPrettyfy();
    leftPrettyfy();
  }
}

En faisant varier k de façon fantaisiste dans la boucle, nous pourrions imprimer une impression triangulaire

1
2  3
4  5  6
7  8  9  10
11 12 13 14 15

C’est pour démontrer que, si vous considérez cela comme un bogue, ce " bogue " est une fonctionnalité utile que nous ne voudrions pas supprimer des langages que nous avons utilisés jusqu’à présent.

9
Blessed Geek

Je trouve que les identificateurs de lettre sont plus lisibles et plus représentatifs du type analysé:

1 - 7f / 10
1 - 7 / 10f

ou:

1 - 7d / 10
1 - 7 / 10d
1
Fred Haslam

Dans mon cas, je faisais ceci:

double a = (double) (MAX_BANDWIDTH_SHARED_MB/(qCount+1));

Au lieu du "correct":

double a = (double)MAX_BANDWIDTH_SHARED_MB/(qCount+1);

Attention aux parenthèses!

0
Felipe Volpato