Cet algorithme permettant de trouver la sum à l’infini d’une série est-il acceptable?

La sum à l’infini des séries suivantes se trouve:

1 1/2 1/3 1/4 1/5 ... 

Selon l’explication d’un scientifique, l’ infini est ce point au-delà duquel tout point est inexistant, c’est-à-dire inf + x = inf ou inf ~ (inf + x) = 0 . Donc, sur la base de cette théorie, l’algorithme suivant a été utilisé:

 float sum=0.0; for(int i=0;;i++){ if((sum+(1.0/i))==sum) break; sum+=(1.0/i); } /* print the value of sum */ 

L’algorithme a été exécuté en C et JAVA et les deux ont donné le résultat sous la forme inf . Les instructions d’impression écrites en C et Java sont respectivement

 printf("%6f",sum); System.out.println(sum); 

EDIT: Le code écrit plus tôt (dans la question) avait une erreur parce que je l’ai tapé, je n’ai pas copié-collé. Désolé. Ceci étant résolu, voici le code sur lequel je baserai ma question:

 float sum=0.0; for(int i=1;;i++){ if((sum+ (1.0/i))==sum) break; sum+=(1.0/i); } /*print the value of sum*/ 

Un de mes amis a dit qu’il avait obtenu la sortie sous forme d’un nombre fractionnaire fini en C. Mais dans mon cas, le programme ne s’est jamais arrêté, à la fois en C et en Java (Cette sortie a été obtenue à partir du nouveau code modifié posté ci-dessus. Ne considérez pas le code défectueux précédent et sa sortie qui était “INF”.) Ma question est la suivante: cet algorithme est-il acceptable? Et si oui, alors j’aimerais savoir le possible de causer différentes sorties en C. Merci.

L’algorithme a été exécuté en C et JAVA et les deux ont donné le résultat sous la forme inf.

C’est parce qu’il y a un bug dans votre code. Vous commencez avec i == 0 . Lorsque vous calculez 1.0 / 0 vous obtenez un fichier INF.

La série est supposée commencer par i == 1

Vous avez modifié la question pour résoudre ce bogue particulier.

Même dans ce cas, vous n’obtiendrez toujours pas une valeur correcte pour la sum à l’infini. La série diverge (va à l’infini) mais, compte tenu de la façon dont vous la calculez, vous ne pourrez pas y arriver.

Finalement, vous atteindrez un point où 1.0/i est trop petit pour changer de sum et vous sortirez de la boucle. Je pense que cela se produira avant i == Integer.MAX_VALUE … mais si ce n’était pas le cas, vous renconsortingez un autre bogue dans votre code. Si Integer.MAX_VALUE Integer.MIN_VALUE , le résultat sera Integer.MIN_VALUE à Integer.MIN_VALUE et vous commencerez à append des termes négatifs à la sum. Oops!


En fait, ce que vous essayez de calculer est la série des harmoniques. Les sums partielles (pour N termes) convergent vers le log e N + E, où E est la constante d’Euler – Mascheroni.

Source: https://en.wikipedia.org/wiki/Harmonic_series_%28mathematics%29#Partial_sums

A partir de là, on devrait pouvoir estimer quand la différence entre la Nième sum partielle et 1.0 / N devient assez grande pour arrêter l’itération.

Une note finale: vous obtiendrez des sums plus précises si vous faites la sum dans la direction opposée; c’est-à-dire en commençant par très grand N et en sommant avec N réduisant à 1.

Il y a beaucoup de problèmes avec votre code. Votre programme ne fonctionne pas, il semble seulement fonctionner.

  • Ne comparez jamais les nombres flottants pour l’égalité .
  • Les ordinateurs ne peuvent pas diviser par zéro.
  • Les littéraux 0.0 sont de type double . Cela signifie que la sum+(1.0/i) calcul sum+(1.0/i) est effectuée sur le type double , qui peut être un type plus grand que le type float sur le système particulier. Votre code suppose que float et double ont la même représentation, il est donc non portable.

    Par conséquent, le résultat peut ne pas être trop grand lors du calcul, ce qui est fait sur le type double , mais il ne tient pas lorsque vous essayez de le montrer dans un float . Utilisez plutôt le préfixe f sur tous les littéraux, à savoir: 1.0f . Ou utilisez simplement le double systématiquement dans tout le programme.

  • Évitez les boucles cryptiques. Il n’est pas nécessaire de déplacer la condition de boucle à l’intérieur du corps de la boucle. Votre boucle devrait ressembler à quelque chose comme for(int i=0; float_compare(sum+1.0f/i, sum); i++) , où float_compare est un moyen de comparer les nombres flottants. Quelque chose comme ça:

     #include  #define EPSILON 0.00001f inline bool float_compare (float x, float y) { return fabsf(result - expectedResult) < EPSILON; } 

Quelques notes La gamme de i est importante – les nombres entiers n’ont que des représentations fixes.

La série 1/1 + 1/2 + 1/3 + 1/4 … est divergente ( wikipedia: sum des réciproques )

La plage d’un int enveloppe, et vous appendiez donc -1/1 -1/2 … qui aurait tendance à 0.

La série avance très lentement à l’infini, de sorte qu’un ordinateur n’est peut-être pas la meilleure façon de la résoudre.