Bonjour,
Les nombres flottants sont représentés en précision limitée avec un arrondi.
Il en résulte que leurs opérations arithmétiques sont approximatives.
Nous le savons très bien, mais on l'oublie souvent.
Cet exemple bien connu est là pour nous le rappeler.
Une solution du problème présenté consiste à utiliser un langage de programmation
qui n'utilise pas les nombres flottants pour représenter les fractions, mais
c'est au prix de la durée des calculs fortement augmentée, pgl10
Bonjour,
MPIR est une bibliothèque utilisable en C++
qui a le type mpf_class pour les flottants en précision sans limite
et le type mpq_class pour les fractions en précision sans limite.
Voici par exemple le programme écrit avec l'utilisation des mpq_class.
#include <iostream> #include <iomanip> #include "mpirxx.h" // Avec : u(0) = 3/2 et u(1) = 5/3 // calcul de la suite : u(n+2) = 2003 - 6002/u(n+1) + 4000/(u(n+1)*u(n)) // => u(2) = 9/5 , u(3) = 17/9 , u(4) = 33/17 , u(5) = 65/33 , ... int main (void) { mpq_class x(3,2); std::cout << "u(0) = " << std::setprecision(13) << x.get_d() << std::endl; mpq_class y(5,3); std::cout << "u(1) = " << std::setprecision(13) << y.get_d() << std::endl; for(int i=2; i < 51; i++) { mpq_class z = 2003 - 6002/y + 4000/(x*y); if(i<10) std::cout << "u(" << i << ") = " << std::setprecision(13) << z.get_d() << std::endl; else std::cout << "u(" << i << ") = " << std::setprecision(13) << z.get_d() << std::endl; x = y; y = z; } }
Pour compiler ce programme il suffit d'ajouter avec le source
les quatre fichiers : mpir.h, mpir.lib, mpirxx.h et mpirxx.lib
issus de mpfr_mpir_x86_x64_msvc2010.zip en provenance
de : http://www.holoborodko.com/pavel/mpfr/
puis d'utiliser le mode Multithread (/MT) et les deux bibliothèques.
A l'exécution, la convergence vers 2 est vérifiée.
Et voici l'affichage du résultat obtenu.
u(0) = 1.5 u(1) = 1.666666666667 u(2) = 1.8 u(3) = 1.888888888889 u(4) = 1.941176470588 u(5) = 1.969696969697 u(6) = 1.984615384615 u(7) = 1.992248062016 u(8) = 1.996108949416 u(9) = 1.998050682261 u(10) = 1.999024390244 u(11) = 1.999511957052 u(12) = 1.999755918965 u(13) = 1.999877944587 u(14) = 1.999938968569 u(15) = 1.999969483353 u(16) = 1.999984741444 u(17) = 1.999992370664 u(18) = 1.999996185317 u(19) = 1.999998092655 u(20) = 1.999999046327 u(21) = 1.999999523163 u(22) = 1.999999761581 u(23) = 1.999999880791 u(24) = 1.999999940395 u(25) = 1.999999970198 u(26) = 1.999999985099 u(27) = 1.999999992549 u(28) = 1.999999996275 u(29) = 1.999999998137 u(30) = 1.999999999069 u(31) = 1.999999999534 u(32) = 1.999999999767 u(33) = 1.999999999884 u(34) = 1.999999999942 u(35) = 1.999999999971 u(36) = 1.999999999985 u(37) = 1.999999999993 u(38) = 1.999999999996 u(39) = 1.999999999998 u(40) = 1.999999999999 u(41) = 2 u(42) = 2 u(43) = 2 u(44) = 2 u(45) = 2 u(46) = 2 u(47) = 2 u(48) = 2 u(49) = 2 u(50) = 2
D'autres solutions équivalentes qui utilisent les fractions
sans utiliser le nombres flottants habituels sont possibles.
Bon amusement, pgl10