ДЗ 2 — Формулы, ветвления и табуляция

Задачи на вычисление выражений, проверку области определения и вывод таблиц значений.

Редактировать источник

Что внутри

Во втором домашнем задании акцент смещается с простого ввода на вычисление формул, проверку корректности аргументов и вывод серий значений.

2.1 «Конус»

Условие. Нужно вычислить объём и полную поверхность усечённого конуса по R, r и h.

Как устроено решение. Программа читает размеры, вычисляет образующую l, затем по формулам получает объём V и площадь S.

Что учесть. В сохранённом исходнике pi объявлена как int, поэтому значение 3.14 обрезается до 3. В разборе важно понимать, что сама идея верна, но точность страдает.

resources/procedural-programming/home-work-2/conus.cpp
#include <iostream>
#include <math.h>
#include <cmath>
using namespace std;

int main()
{
    int l;
    int pi = 3.14;
    float R, r, h, V, S;
    cout << "Enter h: ";
    if (cin >> h && h >= 0)
    {
        cout << "Enter r: ";
        if (cin >> r && r >= 0)
        {
            cout << "Enter R: ";
            if (cin >> R && R >= 0)
            {
                l = sqrt(h * h + (R - r) * (R - r));
                pi = 3.14;
                V = (((pi * h) / 3) * (R * R + r * R + r * r));
                S = (pi * (R * R + (R + r) * l + (r * r)));
                cout << "V: " << V << "\n";
                cout << "S: " << S;
            }
            else
            {
                cout << "Immposible";
                return 0;
            }
        }
        else
        {
            cout << "Immposible";
            return 0;
        }
    }
    else
    {
        cout << "Immposible";
        return 0;
    }
}

2.2 «Разветвление»

Условие. Для введённых x и a нужно вычислить значение кусочной функции.

Как устроено решение. Сохранённый файл работает по двум веткам: если |x| < 1, считается w = a * log(|x|), иначе программа пытается найти w = sqrt(a - x^2).

Что учесть. Здесь хорошо видно, зачем проверять область определения: логарифм требует положительный аргумент, а корень требует неотрицательное подкоренное выражение.

resources/procedural-programming/home-work-2/branchingout.cpp
#include <iostream>
#include <cmath>
using namespace std;
int main() {
    setlocale(0, "");
    double x, a, w, xm;
    cout << "Введите X:";
    cin >> x;
    cout << "Введите A:";
    cin >> a;
    if (cin.fail()) {
        cin.clear();
        cin.ignore();
        cout << "Некорректный ввод! Перезапустите приложение." << endl;
        return 0;
    }
    else {
        cout << "Ввод успешен." << endl;
        xm = fabs(x);
        if (x == 0)
        {
            cout << "Eror";
            return 0;
        }
        else if (xm < 1)
        {
            w = a * log(xm);
        }
        else if (xm >= 1) {
            if ((a - x * x) < 0) {
                cout << "Ответ: отрицательное подкоренное выражение! Нет ответа.";
                return 0;
            }
            else {
                w = sqrt(a - x * x);
            }
        }
    }
    cout << "Ответ: " << w;
    return 0;
}

2.3 «Функция»

Условие. Нужно вычислить выражение от b, x и y с логарифмом и квадратным корнем.

Как устроено решение. В текущем варианте сначала считаются j = b - y и u = b - x, затем при корректной области определения программа выводит z = log(j) * sqrt(u).

Что учесть. Для такой задачи критично уметь назвать ограничения: b - y > 0, а b - x >= 0. Именно эти проверки защищают программу от некорректных вычислений.

resources/procedural-programming/home-work-2/main.cpp
#include <iostream>
#include <math.h>
#include <cmath>
using namespace std;

int main()
{
    float x, y, b, z;
    int j, u;
    cout << "Enter B: ";
    if (cin >> b)
    {
        cout << "Enter X: ";
        if (cin >> x)
        {
            cout << "Enter Y: ";
            if (cin >> y)
            {
                j = b - y;
                u = b - x;
                if (j > 0)
                {
                    if (u != 0) {
                        z = log(j) * sqrt(u);
                        cout << "Answer: " << z;
                        return 0;
                    }
                    else if (u = 0)
                    {
                        cout << "Net resh";
                    }
                }
                else
                {
                    cout << "Net resh";
                    return 0;
                }
            }
            else
            {
                cout << "Eror";
                return 0;
            }
        }
        else
        {
            cout << "Eror";
            return 0;
        }
    }
    else
    {
        cout << "Eror";
        return 0;
    }
}

2.4 «Порядок»

Условие. Нужно вывести 10 натуральных чисел подряд, начиная с корректного значения N.

Как устроено решение. Исходник читает N, задаёт границу N + 10 и печатает числа в цикле while.

Что учесть. В PDF отдельно оговариваются дробные, нулевые и отрицательные случаи. В текущем файле они не обработаны: решение работает как простая печать десяти последовательных целых чисел от введённого N.

resources/procedural-programming/home-work-2/linerow.cpp
#include <iostream>
#include <math.h>
#include <cmath>
using namespace std;

int main()
{
    int N, N10;
    cout << "Enter N: ";
    if (cin >> N)
    {
        N10 = N + 10;

        while (N != N10)
        {
            cout << N << ", ";
            N = N + 1;
        }
    }
    else
    {
        cout << "Eror";
        return 0;
    }
}

2.5 «Табуляция»

Условие. Нужно протабулировать функцию на отрезке от -4 до 4 с шагом 0.5.

Как устроено решение. В сохранённой программе табулируется выражение y = (x^2 - 2x + 2) / (x - 1). Значения от -4 до 0 и от 1.5 до 4 печатаются отдельно, чтобы не попасть на деление на ноль при x = 1.

Что учесть. Это хороший пример, где область определения влияет не только на вычисление, но и на организацию цикла.

resources/procedural-programming/home-work-2/tabulation.cpp
#include <stdlib.h>
#include <math.h>
#include <iostream>
using namespace std;

int main() {
    setlocale(0, "");
    double y;
    for (double x = -4; x <= 0; x = x + 0.5) {
        y = (((x * x) - 2 * x + 2) / (x - 1));
        cout << "Ответ для x = " << x << " y = " << y << endl;
    }
    cout << "Ответ для x = 1 не существует" << endl;
    for (double x = 1.5; x <= 4; x = x + 0.5) {
        y = (((x * x) - 2 * x + 2) / (x - 1));
        cout << "Ответ для x = " << x << " y = " << y << endl;
    }
    return 0;
}