Рассчитать значение функции с использованием циклов while или do while

Модераторы: Hawk, Romeo, Absurd, DeeJayC, WinMain

alexboliam
Сообщения: 5
Зарегистрирован: 16 окт 2017, 01:05

02 ноя 2017, 00:26

Здраствуйте, сейчас прохожу тему с итерационными циклами, надо написать программу, которая "рассчитает с точностью до 6 цифр значение функции Lnx. Сравнить полученное с помощью ряда значение со значением , полученным стандартной функцией."

Вопросы таковы: как задать рассчет до n-ой цифры?(вроде что-то через %, но не уверен)
Как написать именно эту функцию? Чтобы перед непарным членом стоял знак "+", а перед парным "-".
И последнее, через какой цикл все оформить?
Спасибо за внимание!
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Absurd
Сообщения: 1213
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

02 ноя 2017, 01:26

alexboliam писал(а):Здраствуйте, сейчас прохожу тему с итерационными циклами, надо написать программу, которая "рассчитает с точностью до 6 цифр значение функции Lnx. Сравнить полученное с помощью ряда значение со значением , полученным стандартной функцией."
Это сходящаяся последовательность. Каждый член меньше предыдущего не в разы, а на порядок. Это значит что когда N-ный член на порядок меньше 1e-6, то сумма всего остального от N до +Inf на шестой разряд повлиять заведомо уже не сможет, иначе ряд не был бы сходящимся.
alexboliam писал(а): Как написать именно эту функцию? Чтобы перед непарным членом стоял знак "+", а перед парным "-".
(N%2)*2 - 1 Даст -1 для четных N, и 1 для нечетных (остаток от деления на два даст 1 для нечетных, и 0 для четных. Это уможается на два чтобы 1 отобразить на 2 а ноль - на ноль. Потом вычитаем единичку чтобы получить -1 для четных и 1 - для нечетных). Если член умножить на эту величину, то он будет либо положительным, либо отрицательным. Модуль от умножения на единичку не изменится.
alexboliam писал(а): И последнее, через какой цикл все оформить?
Да без разницы, все циклы эквивалентны. Можно написать программу любой сложности пользуясь только for. Или только while. Разница только в удобстве и наглядности для каждого конкретного слячая.
2B OR NOT(2B) = FF
alexboliam
Сообщения: 5
Зарегистрирован: 16 окт 2017, 01:05

02 ноя 2017, 01:44

Absurd писал(а):Это сходящаяся последовательность. Каждый член меньше предыдущего не в разы, а на порядок. Это значит что когда N-ный член на порядок меньше 1e-6, то сумма всего остального от N до +Inf на шестой разряд повлиять заведомо уже не сможет, иначе ряд не был бы сходящимся.


(N%2)*2 - 1 Даст -1 для четных N, и 1 для нечетных (остаток от деления на два даст 1 для нечетных, и 0 для четных. Это уможается на два чтобы 1 отобразить на 2 а ноль - на ноль. Потом вычитаем единичку чтобы получить -1 для четных и 1 - для нечетных). Если член умножить на эту величину, то он будет либо положительным, либо отрицательным. Модуль от умножения на единичку не изменится.


Да без разницы, все циклы эквивалентны. Можно написать программу любой сложности пользуясь только for. Или только while. Разница только в удобстве и наглядности для каждого конкретного слячая.

Спасибо за ответ! Я сначала думал, что последовательность задается как сумма (см. вложение). Но все же не могу понять, как это записать на C++.
У вас нет необходимых прав для просмотра вложений в этом сообщении.
Absurd
Сообщения: 1213
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

02 ноя 2017, 02:00

alexboliam писал(а):Спасибо за ответ! Я сначала думал, что последовательность задается как сумма (см. вложение). Но все же не могу понять, как это записать на C++.

Ну очевидно что нужно накапливать результат в какой-то переменной-аккумуляторе. Если накапливается результат умножения, начальное значение аккумулятора должно быть 1.0. Для суммы начальный элемент - 0.0. Сначала к аккумулятору, который вначале равен нулю, прибавляется результат этого выражения для N=1. Потом - для N=2. И так до тех пор пока модуль очередного члена не станет на порядок меньше 1e-6.

В современном С++ есть шаблон "свертка" (std::reduce или std::accumulate, не помню), которой можно передать множество, бинарную операцию на этом множестве, и нейтральный элемент для этой бинарной операции. Но если ты сделаешь через свертку, то препод спросит у кого ты это списал.
2B OR NOT(2B) = FF
Аватара пользователя
Romeo
Сообщения: 3091
Зарегистрирован: 02 мар 2004, 17:25
Откуда: Крым, Севастополь
Контактная информация:

02 ноя 2017, 02:22

По первой части всё верно, а вот по reduce и accumulate сделаю замечание. Они тут не подходят, так как требуют заранее вычисленных всех значений последовательности. А это условие недостижимо из-за бесконечности ряда.
Entites should not be multiplied beyond necessity @ William Occam
---
Для выделения С++ кода используйте конструкцию [ code=cpp ] Код [ /code ] (без пробелов)
---
Сообщение "Спасибо" малоинформативно. Благодарность правильнее высказать, воспользовавшись кнопкой "Reputation" в виде звёздочки, расположенной в левом нижнем углу рамки сообщения.
Absurd
Сообщения: 1213
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

02 ноя 2017, 02:36

Romeo писал(а):По первой части всё верно, а вот но по reduce и accumulate сделаю замечание. Они тут не подходят, так как требуют заранее вычисленных всех значений последовательности. А это условие недостижимо из-за бесконечности ряда.

Да, я вспомнил. В бусте был такой accumulate, которому указывалось до какого разряда сумма должна сойтись. в std:: такого нет.
2B OR NOT(2B) = FF
alexboliam
Сообщения: 5
Зарегистрирован: 16 окт 2017, 01:05

02 ноя 2017, 02:43

Absurd писал(а):Ну очевидно что нужно накапливать результат в какой-то переменной-аккумуляторе. Если накапливается результат умножения, начальное значение аккумулятора должно быть 1.0. Для суммы начальный элемент - 0.0. Сначала к аккумулятору, который вначале равен нулю, прибавляется результат этого выражения для N=1. Потом - для N=2. И так до тех пор пока модуль очередного члена не станет на порядок меньше 1e-6.

В современном С++ есть шаблон "свертка" (std::reduce или std::accumulate, не помню), которой можно передать множество, бинарную операцию на этом множестве, и нейтральный элемент для этой бинарной операции. Но если ты сделаешь через свертку, то препод спросит у кого ты это списал.

Наверное, это бред, но мне пришло в голову только это :

Код: Выделить всё

int main()
{
    int n = 0;
   float ln = 0;
   float next = ((n%2)*2 - 1)*((pow((a-1),2))/n)
 while(next>0.000001 || next<-0.000001)
    {
     n++;
     ln+=next;
     printf("Current:%.6f\n,ln);
     next = ((n%2)*2 - 1)*((pow((a-1),2))/n);
      
    }
    printf("Ln:\n%.6f\n",ln);
    system("pause");
}
Подскажите, пожалуйста, что мне изменить(если не всё что написал) и добавить. Заранее спасибо!
Absurd
Сообщения: 1213
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

02 ноя 2017, 02:59

Ну можно и поизящней конечно, но что конкретно не устраивает? Ответ неверный? Вы пытались это отлаживать?

Кстати, на всех машинах начиная от Pentium-1 стоит математический сопроцессор, который на внутреннем уровне оперирует только 80-битными величинами. Так что между 32-битовым float и 64-битовым double разницы никакой нет, кроме того что double в два раз точнее. Мне, честно говоря, непонятно на чем вы пытаетесь сэкономить.

Ну и то что у вас это выражение в двух экземплярах это конечно не комильфо. Сейчас оно работает, а потом вы поменяете одно и забудете поменять другое. Или ваш подчиненный забудет. Если вам нужно поверять условие не в начале, а в конце цикла, используйте do { } while().

Кроме того, условие в цикле выглядит подозрительно. В моих программах постоянно какие-то глюки в условии "или", поэтому я стараюсь писать без них. Почему не abs(next)>0.000001 ?

И да, у тебя второй аргумент у функции pow не изменяется и равен двум.
2B OR NOT(2B) = FF
Слива
Сообщения: 133
Зарегистрирован: 19 мар 2016, 10:15

02 ноя 2017, 10:21

float next = ((n%2)*2 - 1)*((pow((a-1),2))/n) - 1 ошибку уже нашел. :D pow(.., 2) - не во 2 степени, а в n степени.
И если в условии пишете сравнение, то его надо писать так:
#inclue <math.h>
while(fabs(next) > 1E-6)
Почему n от 0 начинается? Из ряда четко видно, что n = 1 - инициальное значение.
Можно и попроще знак рассчитать. Заводите переменную
unsigned char Sign = 1;
и потом в цикле после расчета члена ряда пишете:
Sign = -Sign;
и все. А сам член ряда будет такой:
next = Sign*((pow((a-1),n))/n);
Absurd
Сообщения: 1213
Зарегистрирован: 26 фев 2004, 13:24
Откуда: Pietari, Venäjä
Контактная информация:

02 ноя 2017, 11:39

Слива писал(а):Можно и попроще знак рассчитать. Заводите переменную
unsigned char Sign = 1;
и потом в цикле после расчета члена ряда пишете:
Sign = -Sign;
Значение этого знака нужно выводить напрямую из счетчика цикла, поскольку это зависимое значение. Если в коде много левых переменных которые взаимодействуют между собой непонятным образом, то это приводит к тому что рано или поздно кто-то вносит правку где изменяется логика относительно одной переменной, но при этом не трогается поведение другой переменной. И хорошо если проблему удается найти сразу. Иногда ее приходится искать бинарным поиском, перебирая все изменения за несколько недель.
2B OR NOT(2B) = FF
Ответить