2017-01-10 3 views
0

Je multipliant le 2 très grand nombre en java, mais la sortie se multiplient semble être peu étrange
codeMultipliant Grand nombre en java

long a = 2539586720l; 
long b = 77284752003l; 
a*=b; 
System.out.println(a); 
a=(long)1e12; 
b=(long)1e12; 
a*=b; 
System.out.println(a); 

Sortie:

-6642854965492867616 
2003764205206896640 

Dans le premier cas pourquoi le résultat est négatif, si c'est à cause du débordement alors comment se fait-il que le résultat de la seconde est positif? S'il vous plaît expliquer ce comportement? Code

Edit: 

J'utilise mod=100000000009 encore l'opération il est négatif?

a = ((a%mod)*(b%mod))%mod 
+0

Cela peut être dû à une troncature, car le résultat ne peut pas être stocké dans un 'long'. Si "long" ne suffit pas. Essayez d'utiliser 'BigInteger' –

+0

@ redflar3 ce n'est pas un problème, le principal problème est de savoir pourquoi« négatif »sur le premier cas alors que« positif »sur le deuxième cas –

+1

peut supporter jusqu'à (2^63-1 qui est 9e18) où le le résultat de votre première multiplication dépasse 1e20. cela provoque une troncature, donc le résultat n'est pas correct. De même, le second résultat est également tronqué, car il devrait être 1e24. par conséquent utiliser BigInteger –

Répondre

1

Oui. C'est un problème de débordement. La taille est de 8 octets et le range goes from -9,223,372,036,854,775,808 to 9,223,372,036,854,775,807

Si vous voulez multiplier de très gros nombres. Utilisez BigInteger

import java.math.*; 

public static void main(String[] args){ 
    BigInteger bi1, bi2, bi3; 

    bi1 = new BigInteger("2539586720"); //or 1000000000000 
    bi2 = new BigInteger("77284752003"); 

    // multiply bi1 with bi2 and assign result to bi3 
    bi3 = bi1.multiply(bi2); 

    String str = bi1 + " * " + bi2 + " = " +bi3; 
    //Multiplication result is 2539586720 * 77284752003 = 196271329845312200160 
} 
+1

Importer 'java.math.BigInteger' pas' * ' – Michael

2

Le résultat que vous obtenez est généralement un problème de trop-plein, pour un long: java alloue 63 bits pour le nombre et le bit le plus significatif (MSB) pour le signe (0 pour les valeurs positives et 1 pour valeurs négatives) donc 64 bits au total.

savoir De sorte que, Long.MAX_VALUE + 1 égal à -9223372036854775808 parce Long.MAX_VALUE = 2^63 - 1 = 9223372036854775807 = 0x7fffffffffffffffL donc si nous ajoutons à 1, nous obtenons 0x8000000000000000L = Long.MIN_VALUE = -2^63 = -9223372036854775808. Dans ce cas, le MSB passe de 0 à 1, le résultat est donc négatif, ce qui correspond à ce que vous obtenez dans le premier cas d'utilisation.

Si le MSB est réglé sur 1 et vous causer un nouveau débordement avec un certain calcul, il passera à 0 à nouveau (parce que nous ne gardons que les premiers 64 morceaux) de sorte que le résultat sera positif, qui est en fait ce que vous obtenez dans le deuxième cas d'utilisation.

Pour éviter cela, vous devez utiliser BigInteger.

0

Comme par JLS 15.17.1

Si une multiplication déborde entier, alors le résultat est les bits de poids faible du produit mathématique tel que représenté dans un format two's-complément suffisamment grand. Par conséquent, si un débordement se produit, le signe du résultat peut ne pas être identique au signe du produit mathématique des deux valeurs d'opérande.

C'est pourquoi vous obtenez des valeurs négatives et aucune corrélation avec les nombres d'entrée. C'est en raison du fait que long en Java peut représenter seulement de -2^63 à (2^63) -1 et votre résultat est supérieur à ceci.

Afin d'éviter ce problème, lorsque vous traitez l'arithmétique des grands nombres, vous devez toujours utiliser BigInteger. Un exemple de code est donné ci-dessous

BigInteger.valueOf(123L).multiply(BigInteger.valueOf(456L)); 
0

En ce qui concerne le comportement, les deux exemples sont des débordements. Le fait qu'une réponse soit négative n'ajoute aucune signification particulière. Le premier ensemble de nombres que vous avez multiplié se traduit par un long dont le bit le plus significatif est 1, tandis que le dernier ne l'est pas.