web-dev-qa-db-fra.com

Int division: Pourquoi le résultat de 1/3 == 0?

J'écrivais ce code:

public static void main(String[] args) {
    double g = 1 / 3;
    System.out.printf("%.2f", g);
}

Le résultat est 0. Pourquoi et comment résoudre ce problème?

81
Tofiq

Les deux opérandes (1 et 3) sont des nombres entiers. Par conséquent, l'arithmétique des nombres entiers (division ici) est utilisée. En déclarant la variable résultat double, une conversion implicite se produit après division.

La division entière du cours renvoie le résultat réel de la division arrondi à zéro. Le résultat de 0.333... est donc arrondi à 0 ici. (Notez que le processeur ne fait pas d'arrondi, mais vous pouvez toujours le penser de cette façon.)

Notez également que si les deux _ opérandes (nombres) sont donnés sous forme de flottants; 3.0 et 1.0, ou même simplement le premier, l’arithmétique en virgule flottante est utilisée, ce qui vous donne 0.333....

115
Noldorin

1/3 utilise une division entière car les deux côtés sont des entiers.

Vous devez avoir au moins l’un d’eux pour être float ou double.

Si vous entrez les valeurs dans le code source comme votre question, vous pouvez faire 1.0/3; le 1.0 est un double.

Si vous obtenez les valeurs ailleurs, vous pouvez utiliser (double) pour transformer la int en une double.

int x = ...;
int y = ...;
double value = ((double) x) / y;
18
Adrian Smith

Exprimez-le explicitement en tant que double

double g = 1.0/3.0

Cela est dû au fait que Java utilise l'opération de division d'entiers pour 1 et 3 puisque vous les avez entrées en tant que constantes d'entiers.

10
Charlie

Parce que vous faites la division entière.

Comme @Noldorin le dit, si les deux opérateurs sont des nombres entiers, la division en nombres entiers est utilisée.

Le résultat 0.33333333 ne peut pas être représenté sous la forme d'un entier. Par conséquent, seule la partie entière (0) est attribuée au résultat.

Si l'un des opérateurs est une double/float, l'arithmétique en virgule flottante aura lieu. Mais vous aurez le même problème si vous faites cela:

int n = 1.0 / 3.0;
2
Tom

tu devrais utiliser

double g=1.0/3;

ou

double g=1/3.0;

La division entière renvoie un entier.

2
user467871

La solution la plus simple est de le faire 

double g = ((double) 1 / 3);

Puisque vous n’avez pas entré 1.0/3.0, cela vous permet de le convertir manuellement en type de données double puisque Java supposait qu’il s’agissait d’une division Integer. Même si cela impliquait de réduire la conversion. C'est ce qu'on appelle un opérateur de casting.

1
Ramzi El-Jabali

1 et 3 sont des constantes entières. Ainsi, Java effectue une division entière dont le résultat est 0. Si vous voulez écrire des constantes doubles, vous devez écrire 1.0 et 3.0.

1
Reboot

Parce qu'il considère 1 et 3 comme des entiers, arrondissez donc le résultat à 0, de sorte qu'il s'agisse d'un entier.

Pour obtenir le résultat recherché, indiquez explicitement à Java que les nombres sont en double, comme suit:

double g = 1.0/3.0;
1
DanielGibbs

Faire le 1 un float et la division de float sera utilisé

public static void main(String d[]){
    double g=1f/3;
    System.out.printf("%.2f",g);
}
1
sblundy

La conversion en Java est assez simple mais nécessite une certaine compréhension. Comme expliqué dans le JLS pour les opérations entier :

Si un opérateur entier autre qu'un opérateur de décalage a au moins un opérande de type long, l'opération est effectuée avec une précision de 64 bits et le résultat de l'opérateur numérique est de type long. Si l'autre opérande n'est pas long, il est d'abord élargi (§5.1.5) pour taper long par promotion numérique (§5.6). 

Et un exemple est toujours le meilleur moyen de traduire le JLS;) 

int + long -> long
int(1) + long(2) + int(3) -> long(1+2) + long(3)

Sinon, l'opération est effectuée avec une précision de 32 bits et le résultat de l'opérateur numérique est du type int. Si l'un des opérandes n'est pas un int, il est d'abord élargi au type int par une promotion numérique. 

short + int -> int + int -> int

Un petit exemple utilisant Eclipse pour montrer que même l’ajout de deux shorts ne sera pas si facile:

short s = 1;
s = s + s; <- Compiling error

//possible loss of precision
//  required: short
//  found:    int

Cela nécessiterait un casting avec une possible perte de précision.

Il en va de même pour les opérateurs virgule flottante

Si au moins l'un des opérandes d'un opérateur numérique est de type double, l'opération est effectuée à l'aide d'une arithmétique en virgule flottante à 64 bits et le résultat de l'opérateur numérique est une valeur de type double. Si l'autre opérande n'est pas un double, il est d'abord élargi (§5.1.5) pour taper double par promotion numérique (§5.6). 

Donc, la promotion est faite sur le flotteur en double.

Et le mélange des valeurs entières et flottantes donne des valeurs flottantes comme dit 

Si au moins l'un des opérandes d'un opérateur binaire est du type à virgule flottante, l'opération est alors une opération à virgule flottante, même si l'autre est intégrale. 

Ceci est vrai pour les opérateurs binaires mais pas pour les "opérateurs d'assignation" comme +=

Un simple exemple de travail suffit pour le prouver

int i = 1;
i += 1.5f;

La raison en est qu’il ya un casting implicite fait ici, ce sera exécuté comme 

i = (int) i + 1.5f
i = (int) 2.5f
i = 2
1
AxelH

(1/3) signifie division en nombre entier, c’est pourquoi vous ne pouvez pas obtenir de valeur décimale à partir de cette division. Pour résoudre ce problème, utilisez:

public static void main(String[] args) {
        double g = 1.0 / 3;
        System.out.printf("%.2f", g);
    }
0
Maruf Hossain
public static void main(String[] args) {
    double g = 1 / 3;
    System.out.printf("%.2f", g);
}

Puisque 1 et 3 sont tous les deux ints, le résultat n'est pas arrondi mais il est tronqué. Donc, vous ignorez les fractions et ne prenez que des touts.

Pour éviter cela, utilisez au moins l'un de vos nombres 1 ou 3 sous forme décimale 1.0 et/ou 3.0.

0
Bek