Files
oop/labs/lab3/report.typ
2025-09-30 08:21:09 +03:00

550 lines
18 KiB
Typst
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#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)[Лабораторная работа №3]
#align(center)[Использование выражений]
\
\
\ //#align(center)[Вариант 19]
\
\
\
\
\
\
\
#align(right)[Выполнил:]
#align(right)[Дощенников Никита Андреевич]
#align(right)[Группа: К3221]
#align(right)[Проверил:]
#align(right)[Иванов Сергей Евгеньевич]
\
\
#align(center)[Санкт-Петербург]
#align(center)[2025]
#pagebreak()
=== Цель работы:
Изучить и приобрести навыки использования управляющих конструкций для организации вычислений.
=== Упражнение 1. Реализация операторов выбора.
==== Задание 1. Применение конструкции if-else-if.
В этом задании я составил программу, которая выдает одно из сообщений "внутри", "вне" или "на границе" в зависимости от положения точки относительно заштрихованной области на графике, представленном на рисунке.
#align(center)[#image("assets/1.png")]
```cs
using System;
public class Program
{
static void Main(string[] args)
{
Console.Write("x = ");
float x = float.Parse(Console.ReadLine());
Console.Write("y = ");
float y = float.Parse(Console.ReadLine());
if (x * x + y * y < 9 && y > 0)
{
Console.WriteLine("внутри");
}
else if (x * x + y * y > 9 || y < 0)
{
Console.WriteLine("вне");
}
else
{
Console.WriteLine("на границе");
}
}
}
```
Пример работы:
#align(center)[#image("assets/2.png")]
#align(center)[#image("assets/3.png")]
#align(center)[#image("assets/4.png")]
==== Задание 2. Применение оператора switch.
Я создал программу моделирующую работу калькулятора. Пользователем вводится первый операнд, требуемую операцию и второй операнд. Затем производится расчет результата.
```cs
using System;
public class Program
{
static void Main(string[] args)
{
Console.Write("A = ");
double a = double.Parse(Console.ReadLine());
Console.Write("OP = ");
char op = char.Parse(Console.ReadLine());
Console.Write("B = ");
double b = double.Parse(Console.ReadLine());
bool ok = true;
double res = 0;
switch (op)
{
case '+': res = a + b; break;
case '-': res = a - b; break;
case '*': res = a * b; break;
case '/':
case ':':
res = a / b; break;
default: ok = false; break;
}
if (ok)
{
Console.WriteLine("{0} {1} {2} = {3}", a, op, b, res);
}
else
{
Console.WriteLine("Операция не определена");
}
}
}
```
Пример работы:
1) c правильными значениями:
#align(center)[#image("assets/5.png")]
2) при делении на нуль:
#align(center)[#image("assets/6.png")]
Бесконечность, так как в стандарте IEEE-754 прописан такой результат.
3) при делении нуль на нуль:
#align(center)[#image("assets/7.png")]
NaN, опять же в соответствии со стандартом.
4) при неправильной операции:
#align(center)[#image("assets/8.png")]
Мы проваливаемся к значению по умолчанию.
==== Задание 3. Определение високосного года.
Программа, по введенному натуральному числу, определяет, является ли год с номером, равным этому числу, високосным.
```cs
using System;
public class Program
{
public static void Main(string[] args)
{
Console.WriteLine("input a year: ");
int year = int.Parse(Console.ReadLine());
if ((year % 4 == 0 && year % 100 != 0) || (year % 400 == 0))
{
Console.WriteLine("YES");
}
else
{
Console.WriteLine("NO");
}
}
}
```
Пример работы:
#align(center)[#image("assets/9.png")]
#align(center)[#image("assets/10.png")]
=== Упражнение 2. Реализация циклов при работе с данными размерных типов.
==== Задание 1. Использование операторов цикла while, do while и for.
Я написал программу, которая выводит на экран последовательность целых нечетных чисел в строчку через пробел с помощью трех операторов цикла `while`, `do while` и `for`.
```cs
using System;
public class Program
{
public static void Main(string[] args)
{
Console.Write("n = ");
int n = int.Parse(Console.ReadLine());
// while
Console.Write("\nwhile: \t\t");
int i = 1;
while (i <= n)
{
Console.Write(" " + i);
i += 2;
}
// do-while
Console.Write("\ndo while: \t");
i = 1;
do
{
Console.Write(" " + i);
i += 2;
}
while (i <= n);
// for:
Console.Write("\nfor: \t\t");
for (i = 1; i<=n; i+=2)
{
Console.Write(" " + i);
}
}
}
```
Пример работы:
#align(center)[#image("assets/11.png")]
Была написана программа, которая печатает таблицу синусов и их аргументов с периодом 0.01 от `x1` до `x2`.
```cs
using System;
public class Program
{
static void Main(string[] args)
{
double x, x1, x2, y;
Console.WriteLine("input x1:");
x1 = double.Parse(Console.ReadLine());
Console.WriteLine("input x2:");
x2 = double.Parse(Console.ReadLine());
Console.WriteLine("x\t\t sin(x)");
Console.WriteLine("--------------------------");
x = x1;
do
{
y = Math.Sin(x);
Console.WriteLine($"{x:F2}\t {y:F6}");
x = x + 0.01;
}
while (x <= x2);
}
}
```
Пример работы:
#align(center)[#image("assets/12.png")]
```cs
using System;
using System.Globalization;
class Program
{
static void FuncWhile()
{
var ci = CultureInfo.InvariantCulture;
double x1 = double.Parse(Console.ReadLine(), ci);
double x2 = double.Parse(Console.ReadLine(), ci);
double h = double.Parse(Console.ReadLine(), ci);
double x = x1;
while (x <= x2 + 1e-12)
{
double y = Math.Sin(x);
Console.WriteLine($"while: {x.ToString(ci)} {y.ToString(ci)}");
x += h;
}
}
static void FuncDoWhile()
{
var ci = CultureInfo.InvariantCulture;
double x1 = double.Parse(Console.ReadLine(), ci);
double x2 = double.Parse(Console.ReadLine(), ci);
double h = double.Parse(Console.ReadLine(), ci);
double x = x1;
if (h <= 0) return;
do
{
double y = Math.Sin(x);
Console.WriteLine($"do-while: {x.ToString(ci)} {y.ToString(ci)}");
x += h;
} while (x - h < x2 + 1e-12);
}
static int GcdWhile(int a, int b)
{
a = Math.Abs(a);
b = Math.Abs(b);
while (b != 0)
{
int temp = a % b;
a = b;
b = temp;
}
return a;
}
static int GcdDoWhile(int a, int b)
{
a = Math.Abs(a);
b = Math.Abs(b);
int temp;
if (b == 0) return a;
do
{
temp = a % b;
a = b;
b = temp;
} while (b != 0);
return a;
}
static void Main()
{
Console.WriteLine("=== Функция с while ===");
FuncWhile();
Console.WriteLine("=== Функция с do-while ===");
FuncDoWhile();
Console.WriteLine("Введите два числа для НОД (while):");
int a = int.Parse(Console.ReadLine());
int b = int.Parse(Console.ReadLine());
Console.WriteLine($"НОД (while): {GcdWhile(a, b)}");
Console.WriteLine("Введите два числа для НОД (do-while):");
a = int.Parse(Console.ReadLine());
b = int.Parse(Console.ReadLine());
Console.WriteLine($"НОД (do-while): {GcdDoWhile(a, b)}");
}
}
```
- *while* подходит, когда важно проверять условие до входа в цикл (может выполниться 0 раз).
- *do…while* удобен, когда тело должно выполниться минимум один раз.
- Для функций на интервале *do…while* проще гарантирует вывод крайней точки.
- Для алгоритма Евклида оба варианта дают одинаковый результат; *while* короче, *do…while* более наглядно выражает шаг алгоритма.
==== Задание 2. Расчет суммы, используя операторы перехода.
Составлена программа, которая реализует сумму
$
s = sum_(i = 1)^(100) i,
$
для $i$, находящихся от $1$ до $k$ и от $m$ до $100$.
```cs
using System;
class Program
{
static void Main()
{
Console.Write("Введите k: ");
int k = int.Parse(Console.ReadLine());
Console.Write("Введите m: ");
int m = int.Parse(Console.ReadLine());
int s = 0;
for (int i = 1; i <= 100; i++)
{
if (i > k && i < m) continue;
s += i;
}
Console.WriteLine("Сумма = " + s);
}
}
```
Пример работы:
#align(center)[#image("assets/13.png")]
==== Задание 3. Стрельба по мишени.
Разработа программа, имитирующая стрельбу по мишени.
```cs
using System;
class Program
{
static int VariantFromStudentNumber(int n) => (n % 2 != 0) ? 1 : 2;
static int ScoreVariant1(double x, double y)
{
var r = Math.Sqrt(x * x + y * y);
if (r <= 1) return 10;
if (r <= 2) return 5;
if (r <= 3) return 2;
return 0;
}
static int Sector(double x, double y)
{
var a = Math.Atan2(y, x);
if (a > Math.PI / 4 && a <= 3 * Math.PI / 4) return 1;
if (a > -Math.PI / 4 && a <= Math.PI / 4) return 5;
if (a > -3 * Math.PI / 4 && a <= -Math.PI / 4) return 2;
return 3;
}
static int ScoreVariant2(double x, double y)
{
var r = Math.Sqrt(x * x + y * y);
if (r <= 1) return 10;
if (r <= 3) return Sector(x, y);
return 0;
}
static void Main()
{
Console.Write("Номер по списку: ");
int student = int.Parse(Console.ReadLine());
int variant = VariantFromStudentNumber(student);
Console.Write("Сколько выстрелов: ");
int n = int.Parse(Console.ReadLine());
Console.Write("Случайный центр? (y/n): ");
bool rndCenter = Console.ReadLine().Trim().ToLower() == "y";
Console.Write("Случайная помеха? (y/n): ");
bool noise = Console.ReadLine().Trim().ToLower() == "y";
var rnd = new Random();
double cx = 0, cy = 0;
if (rndCenter)
{
cx = rnd.NextDouble() * 2 - 1;
cy = rnd.NextDouble() * 2 - 1;
}
int sum = 0;
for (int i = 0; i < n; i++)
{
Console.Write($"Выстрел {i + 1} (x y): ");
var parts = Console.ReadLine().Trim().Split(new[] { ' ', '\t' }, StringSplitOptions.RemoveEmptyEntries);
double x = double.Parse(parts[0]);
double y = double.Parse(parts[1]);
if (noise)
{
x += (rnd.NextDouble() * 0.2 - 0.1);
y += (rnd.NextDouble() * 0.2 - 0.1);
}
x -= cx;
y -= cy;
int s = variant == 1 ? ScoreVariant1(x, y) : ScoreVariant2(x, y);
sum += s;
Console.WriteLine($"Очки: {s}, сумма: {sum}");
}
Console.WriteLine($"Итоговая сумма: {sum}");
}
}
```
Пример работы:
#align(center)[#image("assets/14.png")]
=== Code review. (by #link("https://zzzcode.ai")[zzzcode.ai])
*Резюме*
Код выполняет несколько задач, включая определение положения точки относительно круга, выполнение арифметических операций, проверку високосного года, вывод чисел и вычисление НОД. Однако, в коде присутствуют некоторые недостатки, которые могут быть улучшены для повышения его качества и удобства использования.
*Ошибка*
В коде отсутствует обработка исключений при парсинге пользовательского ввода. Это может привести к сбоям программы, если пользователь введет некорректные данные. Рекомендуется использовать TryParse для безопасного парсинга.
*Стиль кода*
Стиль кода в целом соответствует стандартам C\#. Однако, в некоторых местах можно улучшить читаемость, добавив комментарии и более описательные имена переменных. Например, вместо `x1`, `x2` можно использовать `startX`, `endX`.
*Структура кода*
Код разбит на несколько классов, что хорошо для организации. Однако, каждый класс содержит метод `Main`, что не является хорошей практикой. Рекомендуется создать один класс с единственным методом `Main`, а остальные функции вынести в отдельные методы.
`Читаемость`
Читаемость кода можно улучшить, добавив комментарии, объясняющие логику выполнения. Также стоит использовать более понятные имена переменных и методов, чтобы другие разработчики могли быстрее понять, что делает код.
`Производительность`
Код выполняется достаточно быстро для небольших входных данных. Однако, в случае больших объемов данных, стоит рассмотреть возможность оптимизации, например, путем использования более эффективных алгоритмов.
Масштабируемость
Код не очень масштабируем, так как он жестко привязан к конкретным задачам. Рекомендуется использовать более модульный подход, чтобы можно было легко добавлять новые функции без изменения существующего кода.
`Безопасность`
Безопасность кода можно улучшить, добавив обработку исключений и проверку входных данных. Это поможет избежать потенциальных уязвимостей, связанных с некорректным вводом.
`Обработка ошибок`
Обработка ошибок в коде отсутствует. Рекомендуется использовать конструкции `try-catch` для обработки возможных исключений, особенно при работе с пользовательским вводом и парсингом данных.
*Заключение*
В целом, код выполняет свои функции, но требует улучшений в области обработки ошибок, читаемости и структуры. Рекомендуется внести изменения, чтобы сделать код более безопасным, масштабируемым и удобным для чтения.
=== Выводы.
В ходе проделанной работы, я изучил и приобрел навыки использования управляющих конструкций для организации вычислений.