#set text(size: 1.3em)

#show raw.where(block: false): box.with(
  fill: luma(240),
  inset: (x: 3pt, y: 0pt),
  outset: (y: 3pt),
  radius: 2pt,
)

#show raw.where(block: true): block.with(
  fill: luma(240),
  inset: 10pt,
  radius: 4pt,
)

// title

#align(center)[Санкт-Петербургский национальный исследовательский университет информационных технологий, механики и оптики]
\
\
\
#align(center)[Факультет инфокоммуникационных технологий]
#align(center)[Направление подготовки 11.03.02]
\
\
#align(center)[Лабораторная работа №4]
#align(center)[Создание и использование методов]
\
\
\ //#align(center)[Вариант 19]
\
\
\
\
\
\
\
#align(right)[Выполнил:]
#align(right)[Дощенников Никита Андреевич]
#align(right)[Группа: К3221]
#align(right)[Проверил:]
#align(right)[Иванов Сергей Евгеньевич]
\
\
#align(center)[Санкт-Петербург]
#align(center)[2025]

#pagebreak()

=== Цель работы:

Изучить и приобрести навыки работы с методами класса.

=== Упражнение 1. Использование параметров в методах, возвращающих значения.

Я создал класс `Utils` и определил в нем метод `Greater`, который принимает 2 целочисленных параметра и возвращает больший из них.

Тело метода:

```cs
public static int Greater(int a, int b)
{
    if (a > b)
        return a;
    else
        return b;
}
```

Тест:

```cs
static void Main(string[] args)
{
    int x, y;

    Console.WriteLine("Введите первое число: ");
    x = int.Parse(Console.ReadLine());
    Console.WriteLine("Введите второе число: ");
    y = int.Parse(Console.ReadLine());

    int greater = Utils.Greater(x, y);

    Console.WriteLine("Большим из чисел {0} и {1} является {2} ", x, y, greater);
}
```

Пример:

#align(center)[#image("assets/1.png")]

=== Упражнение 2. Использование в методах параметров, передаваемых по ссылке

Я создал метод `Swap`, который меняет местами значения параметров. При этом использовались параметры, передаваемые по ссылке:

```cs
public static void Swap(ref int a, ref int b)
{
        int temp = a;
        a = b;
        b = temp;
}
```

Тест:

```cs
Console.WriteLine("До swap: \t" + x + " " + y);
Utils.Swap(ref x, ref y);
Console.WriteLine("После swap: \t" + x + " " + y);
```

Пример:

#align(center)[#image("assets/2.png")]

=== Упражнение 3. Использование возвращаемых параметров в методах.

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

```cs
public static bool Factorial(int n, out int answer)
{
    int k;
    int f = 1;
    bool ok = true;

    try
    {
        checked
        {
            for (k = 2; k <= n; ++k)
            {
                f = f * k;
            }
        }
    }
    catch (Exception)
    {
        f = 0;
        ok = false;
    }

    answer = f;
    return ok;
}
```

Тест:

```cs
int f;
bool ok;

Console.WriteLine("Number for factorial:");
x = int.Parse(Console.ReadLine());

ok = Utils.Factorial(x, out f);

if (ok)
    Console.WriteLine("Factorial(" + x + ") = " + f);
else
    Console.WriteLine("Cannot compute this factorial");
```

Пример:

#align(center)[#image("assets/3.png")]

=== Упражнение 4. Расчет площади треугольника с помощью метода.

В этом упражнении я создал класс `Operation` который умеет считать площадь треугольника, проверять треугольник на существование и считать площадь для равностороннего треугольника.

```cs
using System;

public class Operation
{
    public static double TriangleArea(double a, double b, double c)
    {
        double p = (a + b + c) / 2;
        bool exists = CheckTriangle(a, b, c);
        if (!exists)
            return -1;

        return Math.Sqrt(p * (p - a) * (p - b) * (p - c));
    }

    public static double TriangleArea(double a)
    {
        return TriangleArea(a, a, a);
    }


    public static bool CheckTriangle(double a, double b, double c)
    {
        if (a <= 0 || b <= 0 || c <= 0) return false;

        double maxSide = Math.Max(Math.Max(a, b), Math.Max(b, c));

        if (maxSide >= a + b + c - maxSide) return false;

        return true;
    }

    public static int SolveQuadratic(int a, int b, int c, out double x1, out double x2)
    {
        double d = b * b - 4 * a * c;
        if (d > 0)
        {
            x1 = (-b + Math.Sqrt(d)) / (2 * a);
            x2 = (-b - Math.Sqrt(d)) / (2 * a);
            return 1;
        }
        else if (d == 0)
        {
            x1 = x2 = -b / (2 * a);
            return 0;
        }
        else
        {
            x1 = x2 = -1;
            return -1;
        }
    }
}
```

Тесты:

```cs
Console.WriteLine("choose the type of the triangle. type 1 for equilateral else 2: ");
int triangleType = int.Parse(Console.ReadLine());

switch (triangleType)
{


case 1:
    Console.WriteLine("input side length: ");
    double a = double.Parse(Console.ReadLine());
    Console.WriteLine("area = {0}", Operation.TriangleArea(a));
    break;
case 2:
    Console.WriteLine("input first side length: ");
    double sideA = double.Parse(Console.ReadLine());
    Console.WriteLine("input second side length: ");
    double sideB = double.Parse(Console.ReadLine());
    Console.WriteLine("input third side length: ");
    double sideC = double.Parse(Console.ReadLine());
    Console.WriteLine("area = {0}", Operation.TriangleArea(sideA, sideB, sideC));
    break;
default:
    Console.WriteLine("invalid triangle type");
    break;
}
```

Пример:

#align(center)[#image("assets/4.png")]

=== Упражнение 5. Вычисление корней квадратного уравнения.

В этом упражнении я реализовал метод вычисления квадратного уравнения.

```cs
public static int SolveQuadratic(int a, int b, int c, out double x1, out double x2)
{
    double d = b * b - 4 * a * c;
    if (d > 0)
    {
        x1 = (-b + Math.Sqrt(d)) / (2 * a);
        x2 = (-b - Math.Sqrt(d)) / (2 * a);
        return 1;
    }
    else if (d == 0)
    {
        x1 = x2 = -b / (2 * a);
        return 0;
    }
    else
    {
        x1 = x2 = -1;
        return -1;
    }
}
```

Тесты:

```cs
Console.WriteLine("input coefficient a: ");
int coef_a = int.Parse(Console.ReadLine());
Console.WriteLine("input coefficient b: ");
int coef_b = int.Parse(Console.ReadLine());
Console.WriteLine("input coefficient c: ");
int coef_c = int.Parse(Console.ReadLine());

double x1, x2;
int res = Operation.SolveQuadratic(coef_a, coef_b, coef_c, out x1, out x2);

if (res == 1)
{
    Console.WriteLine("Корни уравнения с коэффициентами a = результат, b = результат, c = результат равны x1 = {0}, x2 = {1}.", x1, x2);
}
else if (res == 0)
{
    Console.WriteLine("Корень уравнения с коэффициентами a = результат, b = результат, c = результат равны один x1 = x2 = {0}", x1);
}
else
{
    Console.WriteLine("Корней уравнения с коэффициентами a = результат, b = результат, c = результат нет.");
}
```

Пример:

#align(center)[#image("assets/5.png")]
#align(center)[#image("assets/6.png")]
#align(center)[#image("assets/7.png")]

=== Вывод.

В ходе проделанной работы, я изучил и приобрел навыки работы с методами класса.

=== Code review. (by #link("https://zzzcode.ai")[zzzcode.ai])

*Резюме*

Данный код реализует несколько математических операций, включая вычисление площади треугольника, решение квадратного уравнения и вычисление факториала. Код написан на C\# и включает в себя классы `Operation`, `Program` и `Utils`. В целом, код выполняет свои функции, но требует улучшений в области обработки ошибок, читаемости и структуры.

*Ошибка*

В методе `TriangleArea` возвращается -1 в случае, если треугольник не существует. Это может вызвать путаницу, так как -1 может быть интерпретировано как валидное значение площади. Рекомендуется использовать исключения для обработки ошибок.

*Стиль кода*

Код в целом следует стандартам C\#, однако есть некоторые моменты, которые можно улучшить:

    Использование var для переменных, где тип очевиден.
    Избегание магических чисел, таких как -1, для обозначения ошибок.

*Структура кода*

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

*Читаемость*

Код читаем, но можно улучшить его с помощью:

    Добавления комментариев для сложных участков кода.
    Использования более описательных имен переменных и методов.

*Производительность*

Код работает эффективно для небольших входных данных. Однако, для больших значений, особенно в методе `Factorial`, стоит рассмотреть использование более эффективных алгоритмов или библиотек.

*Масштабируемость*

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

*Безопасность*

Код не содержит явных уязвимостей, но стоит добавить проверки на вводимые данные, чтобы избежать исключений при некорректном вводе.

*Обработка ошибок*

Обработка ошибок в коде минимальна. Рекомендуется использовать исключения для более четкой обработки ошибок, а также добавлять проверки на вводимые данные.

*Заключение*

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