Этот алгоритм позволяет найти сумму до бесконечности серии, приемлемой?

Вывести сумму в бесконечность следующей серии:

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

Согласно объяснению некоторого ученого, бесконечность – это точка, за которой не существует какой-либо точки, т. Е. Inf + x = inf или inf ~ (inf + x) = 0 . Итак, на основе этой теории был использован следующий алгоритм:

 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 */ 

Алгоритм выполнялся в C и JAVA, и оба дали выход как inf . Операторы печати, написанные на C и Java, соответственно,

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

EDIT: код, написанный ранее (в вопросе), был ошибкой, потому что я набрал его, не скопировал-вставить. Простите за это. Это решение, вот код, на который я поставил бы свой вопрос:

 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*/ 

Один мой друг сказал, что он получил выход как конечное дробное число в C. Но в моем случае программа никогда не прерывалась, как на C, так и на Java (этот вывод был получен из нового отредактированного кода, вышедшего выше. Не учитывайте предыдущий код неисправности и его вывод, который был «INF».) Мой вопрос: этот алгоритм приемлем? И если да, то я хотел бы узнать о возможных причинах различных выходов в C. Благодарю.

Алгоритм выполнялся в C и JAVA, и оба дали выход как inf.

Это потому, что в вашем коде есть ошибка. Вы начинаете с i == 0 . Когда вы вычисляете 1.0 / 0 вы получаете INF.

Предполагается, что серия начнется с i == 1

Вы отредактировали вопрос, чтобы исправить эту ошибку.

Тем не менее, вы все равно никогда не получите правильное значение для суммы до бесконечности. Серия расходится (идет к бесконечности), но, учитывая то, как вы ее вычисляете, вы не сможете добраться туда.

В конце концов вы достигнете точки, где 1.0/i слишком мало, чтобы изменить sum и вы выйдете из цикла. Я ожидаю, что это произойдет до того, как i == Integer.MAX_VALUE … но если это не так, тогда вы столкнетесь с ДРУГОЙ ошибкой в ​​своем коде. Если i когда-либо достиг Integer.MAX_VALUE тогда он Integer.MIN_VALUE в Integer.MIN_VALUE и вы начнете добавлять к сумме отрицательные термины. К сожалению!


Фактически, то, что вы пытаетесь вычислить, это Гармоническая серия. Частичные суммы (для N слагаемых) сходятся к log e N + E, где E – постоянная Эйлера-Маскерони.

Источник: https://en.wikipedia.org/wiki/Harmonic_series_%28mathematics%29#Partial_sums

Из этого следует уметь оценить, когда разница между N-й частичной суммой и 1.0 / N становится достаточно большой, чтобы остановить итерацию.

Конечная нота: вы получите более точные суммы, если вы суммируете в противоположном направлении; т.е. начиная с очень большого N и суммируя с N уменьшением до 1.

С вашим кодом много проблем. Ваша программа не работает, она работает только.

  • Никогда не сравнивайте числа float для равенства .
  • Компьютеры не могут делить на ноль.
  • Литералы 0.0 имеют тип double . Это означает, что sum+(1.0/i) вычислений sum+(1.0/i) выполняется по типу double , который может быть более крупным, чем float для конкретной системы. Ваш код предполагает, что float и double имеют одинаковое представление, поэтому он не переносится.

    Поэтому результат может быть не слишком большим во время вычисления, который выполняется по типу double , но он не подходит, когда вы пытаетесь отобразить его обратно в float . Вместо этого используйте f префикс для всех литералов, то есть: 1.0f . Или просто используйте double последовательность по всей программе.

  • Избегайте критических петель. Нет необходимости перемещать условие цикла внутри тела цикла. Ваш цикл должен выглядеть примерно так: for(int i=0; float_compare(sum+1.0f/i, sum); i++) , где float_compare – это способ сравнения чисел с плавающей запятой. Что-то вроде этого:

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

Некоторые примечания Диапазон i важен – целые числа имеют только фиксированные представления.

Серия 1/1 + 1/2 + 1/3 + 1/4 … расходится ( википедия: сумма рецептур )

Диапазон int wraps, и поэтому вы также добавляете -1/1 -1/2 …, который будет иметь тенденцию 0.

Серия продвигается до бесконечности очень медленно, поэтому компьютер не может быть лучшим способом его работы.