7
votes

Le dernier algorithme théorique de Fermat

Je prends Cette Définition du dernier théorème de Fermat.

i J'ai essayé de coder un algorithme pour le valider pour les petites valeurs: xxx

et ceci est un écran d'une sortie de sortie: image

Comment est-il possible? Je manque quelque chose à propos de "superbes entiers" dans la programmation C ++ pouvant avoir un résultat erroné?


7 commentaires

Êtes-vous au courant du forum de mathématiques chez math.stackexchange.com ?


Je pense que vous voulez collecter des preuves empiriques jusqu'à certains n dans ℤ, plutôt que de prouver. @MarCaudet Je pense que cela reste une question de trop-plein si nous renvoyons toute la preuve.


@MarCaudet Toute question contenant du code est généralement hors tension pour mathématiques .


Une preuve de force brute prendra infiniment longtemps à compléter.


Astuce: COUT << POW (C, N) << Endl;


OMG Vous avez trouvé un contre-exemple au dernier théorème de Fermat !!!


Question très divertissante. Lit comme une bonne tentative de preuve contre le théorème du dernier Fermat.


3 Réponses :


13
votes

Vos fonctions POW () débordent; Rappelez-vous un int a une taille limitée.

Par exemple, POW (256, 4) déborde de 32 bits, POW (256, 8) sur 64 bits, même si vous utilisez des types de données non signés.

Techniquement INT Overflow est comportement non défini donc, n'importe quoi pourrait arriver, y compris une enveloppe (à droite à 0), ou démons nasaux .

non signé int Les calculs sont modulo 2 élevés à la puissance de la largeur selon la norme; C'est-à-dire enveloppera toujours.


6 commentaires

Il appelle probablement std :: pow ici qui utilise des flotteurs. Ce qui en fait encore un débordement, mais la nature du débordement est encore plus complexe.


Bon point. Bien que j'ai une surcharge POW () pour deux entiers.


N'est-ce pas seulement UB pour Signé entiers?


Il n'y a pas de débordement pour les entiers non signés, les calculs sur ceux-ci sont modulo 2 ^ largeur par la norme. Cependant , ici, nous avons un Double résultat de POW () et convertissant une valeur hors plage d'un type de point flottant en Un type d'entier non signé invoque un comportement indéfini, contrairement à la conversion d'un type entier. (CC @harold) (et ici, nous avons signé des entiers de toute façon.)


@HAROLD - Vous êtes correct; J'ai modifié ma réponse. Merci.


@Daniel Fischer; J'ai modifié ma réponse pour inclure Modulo 2 ^ largeur



2
votes

int sont limités à 32 bits (y compris le bit de signalisation), de sorte que les valeurs élevées "enveloppant" au-delà 2147483647. C / C ++ n'ont pas de type de données intégré pour des valeurs arbitrairement importantes. < / p>

Pour réduire quelque peu le problème, vous pouvez utiliser le type long ou non signé long (64 bits sur des plates-formes 64 bits). Certains compilateurs prennent également en charge 64 bits sur des plates-formes 32 bits, si vous utilisez long long .

Edit: Comme indiqué dans un commentaire ci-dessous, les limites ne s'appliquent pas de manière égale à toutes les implémentations de C / C ++, mais pour la plupart des systèmes non intégrés que vous verrez aujourd'hui, ce sont les limites que vous allez voir.


2 commentaires

-1 Les tailles réelles des types entier sont définies en C ++. En particulier, int n'est pas toujours 32 bits en taille et long n'est pas toujours plus grand que int (bien que les deux sont vrais pour l'IDE montrant dans la capture d'écran de l'OP).


Correct. J'aurais pu l'expliquer plus généralement, mais cela ne fait aucune différence dans le contexte de cette question particulière. Il n'y a pas de mise en œuvre que je connaisse de cela pourrait contenir pow (927, 104) dans un int . Merci de clarifier, cependant.



7
votes

Est-ce que je manque quelque chose

vous êtes. Beaucoup beaucoup réellement. Laissez-moi énumérer.

  1. Types . Tous les numéros en C ++ sont des entiers. En particulier, le résultat de pow n'est pas un entier.
  2. précision . Ces types qui ne sont pas entiers ont une précision limitée en C ++. En mathématiques, 1 et 1.000000000000000000000000000000000000000000000000000000982 sont différents. Dans votre programme C ++, bonne chance avec ça.
  3. limites . Les nombres entiers et non entiers en C ++ sont limités dans la gamme de valeurs qu'elles peuvent assumer. Une variable de type int est garantie pour pouvoir contenir des nombres compris entre -32767 à 32767 inclusivement. De nombreuses mises en œuvre soutiennent beaucoup plus que cela, disons -2147483648 à 2147483647. De nombreuses implémentations ont d'autres types pouvant contenir des gammes de nombres plus larges, par exemple. 0-18446744073709551616 ou parfois à 340282366920938463463374607431768211456 ou même 115792089237316195423570985008687907853269984665640564039457584007913129639936. (Si vous pouvez prendre logarithmes des numéros 100 chiffres dans votre tête, vous remarquerez que toutes ces limites sont des puissances de 2 ou quelque chose proche de cela). À titre de comparaison, 927 à la puissance de 104 est 376957467458457979751155893254582133603833255821602148851832991547421266649046326838345134050350882042675908426098865621401193999321757163912667101283653576225503152314408933435079267041822928198211089834145222519701307017745008621307049171220994632585789166175212394809510781938945415209193278956111609706241.

0 commentaires