user10429306

user10429306

На Пикабу
в топе авторов на 861 месте
579 рейтинг 30 подписчиков 1 подписка 29 постов 0 в горячем
4

Тернарная операция и логические операторы. Синтаксис C#

Из этой лекции вы узнаете о логических операторах, тернарной операции, познакомитесь с сокращенной формой конструкции ветвления с оператором «if».

Классическую и расширенную форму конструкции ветвления с оператором «if», удобно использовать при написании информативного кода, когда один из блоков содержит справочную информацию о выполнение или невыполнение операции. За такую информативность ветвления приходится платить нагрузкой на аппаратную часть вычислительной системы, так как увеличивается количество операций. Страдает удобочитаемостью кода. К примеру, классическая формы if…else занимает восемь строк программного кода, поэтому каждая операция вложения одной формы в другую, будет увеличивать программный код на восемь строк.

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

Нам для учебных целей понадобятся нижеследующие логические операторы

Логический оператор— И —&&. Результатом связки двух операций отношений будет true, если результат в обоих операндах (операциях отношения)) будет true, в остальных случаях — false. Заменяет операцию вложения в конструкции ветвления.

Логический оператор — ИЛИ —||. Результатом связки двух операций отношений будет true, если результат в одном из операндов будет true, в остальных случаях — false. Заменяет расширенную конструкцию if…else if…else.

Логическая инверсия (отрицание)—НЕ —!= (отрицание). Используется для изменения результата вычисления операции отношения с true на false или наоборот.

Нижеприведенная таблица помогает правильно составить логические выражения. Где, 0 — ложь, а 1 — истина.

Напишем программу, определяющую принадлежность точки отрезку с координатами [0, 5].

Для получения результата о принадлежности точки заданному отрезку, составим логическое выражение, состоящее из отношения 0 < = point и point <= 5 соединенное логическим оператором &&.

static void Main(string[] args)

{

int point = -2;

if ((0 <= point) && (point <= 5))

{


{

Console.WriteLine("Точка принадлежит отрезку");

}

}

else

{

Console.WriteLine("Точка не принадлежит отрезку");

}

}

Логическое выражение —(0 <= point) && (point <= 5) вычисляет результат двух операций отношения, а оператор && (логическое И) заменяет собой операцию вложения классической формы конструкции ветвления с оператором if.

Усложним задачу и проверим принадлежность точки двум отрезкам с координатами [0, 5]  и [6, 9]

Для этого добавим в предыдущий код проверку принадлежности второму отрезку.

static void Main(string[] args)

{

int point = 8;

if (((0 <= point) && (point <= 5)) || ((6 <= point) && (point <= 9)))

{


{

Console.WriteLine("Точка принадлежит одному из отрезков");

}

}

else

{

Console.WriteLine("Точка не принадлежит ни одному из отрезков");

}

}

Здесь, в качестве операндов выступают логические выражения с оператором &&, а оператором связкой является логический оператор —||.

Логический оператор « | | — ИЛИ» заменяет расширенную форму  if…else if…else. Таким образом, получился компактный, но малоинформативный программный код, который не может сообщить, какому именно отрезку принадлежит точка.

Ну и уж если мы начали писать компактный, но малоинформативный программный код, познакомимся с неполной(сокращенной) формой оператора if и тернарной операцией.

Неполная форма конструкции с оператором if  — это форма без блока else. Тем не менее, даже неполная форма может менять ход выполнения программы. 

Пример программы, изменения процентной ставки по кредиту неработающему заемщику. Переменная job, со значением ноль, указывают на отсутствие работы.

static void Main(string[] args)

{

int job = 0;

double rate = 15;

if(job==0)

{

rate = rate * 1.1;

}

Console.WriteLine("Ставка по кредиту = " + rate);

}

Тот же самый результат можно получить, используя тернарную операцию.

Тернарная операция, это операция над тремя операндами (это повлияло на название). Тернарная операция представляет собой конструкцию, где переменная инициализируется значением второго или третьего операнда.

string result = 0 < 1? "Истина" : "Ложь";

Первый операнд — это логическое выражение 0 <1, после оператора «?», через двоеточие, перечисляются значения второго «Истина»  и третьего операнда «Ложь».

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

Пример программы с тернарной операцией по проверке положительности числа.

static void Main(string[] args)

{

int number = 2;

string result = 0 < number ? "Положительное" : "Отрицательное";

Console.WriteLine("Число " + number + " " + result);

}

Значениями операндов могут выступать не только значения, но и переменные.

Решим задачу по проверке принадлежности точки двум отрезкам с координатами [0, 5]  и [6, 9]

static void Main(string[] args)

{

int point = -8;

bool compare = (((0 <= point) && (point <= 5)) || ((6 <= point) && (point <= 9)));

string textTrue = "Точка принадлежит одному из отрезков";

string textFalse = "Точка не принадлежит ни одному из отрезков";

string result = compare ? textTrue : textFalse;

Console.WriteLine(result);

}

В заключении.

Выбор конструкции ветвления — это всегда выбор между информативностью и размером программного кода. Универсальной конструкцией является классическая форма конструкции условного оператора с условием, представляющим собой цепочку операций отношения, связанных логическими операторами. Такой код не большой по размеру и позволяет, по мере необходимости выводить какие-то сервисные сообщения или информацию об ошибках.

На этом занятие закончено.

Вы можете самостоятельно найти задачи для закрепления теоретического материала или для получения задач с ответами отправьте письмо на basicprog@mail.ru

Удачи в выполнении практических заданий!

Показать полностью 2
5

Расширенная форма и вложения оператора if. Синтаксис C#

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

Но мир задач намного разнообразней и зачастую одному условию соответствует выбор из множества путей.

Но мир задач намного разнообразней и зачастую одному условию соответствует выбор из множества путей. Для решения таких задач используется расширенная форма конструкции с оператором условного перехода «if» вида — if…else if…else.

Напишем программу сравнения двух чисел, где единственным условием является сравнение чисел, но используется при этом в трех вариациях.

static void Main(string[] args)

{

int a = 2;

int b = 2;

if (a < b)

{

Console.WriteLine("A меньше B");

}

else if (a > b)

{

Console.WriteLine("A больше B");

}

else

{

Console.WriteLine("Значения переменных равны");

}

}

В противовес «одно условие, множество путей» существуют задачи, где один путь зависит от выполнения нескольких взаимосвязанных условий. Для решения таких задач используются, вложенные друг в друга, конструкции с классической  формой if…else.

Напишем код проверяющий логин и пароль, где доступ разрешен только после проверки пароля. Пароль в свою очередь проверяется, только после получения результата «истинность» проверки логина.

Допустим, что логин состоит из символов— 123, а пароль —456.

static void Main(string[] args)

{

string login = "123";

string password = "456";

Console.WriteLine("Введите логин");

string loginIn = Console.ReadLine();

if (loginIn == login)

{

Console.WriteLine("Введите пароль");

string passwordIn = Console.ReadLine();

if(passwordIn == password)

{

Console.WriteLine("Доступ разрешен");

}

else

{

Console.WriteLine("Пароль не верен");

}

}

else

{

Console.WriteLine("Логин не верен");

}

}

Здесь, в строке if (loginIn == login) происходит вычисление операции отношения между оригиналом и введенным значением пароля. В случае результата true, управление программой переходит конструкции ветвления с проверкой пароля, в случае false, блок else выводит сообщение «Логин не верен».

Если проверка логина прошла успешно, управление программой передается блоку проверки пароля.

Расширенная форма и вложения оператора if. Синтаксис C#

Вложенность операций позволяет сделать сколько угодно вложений, как в блок истинности условного оператора, так и в его блок ложности.

Напишем программу проверки, будет ли гражданин призван на срочную службу. Оценим это по следующим признакам. Возраст от 18 до 30 лет. Количество детей менее двух.

static void Main(string[] args)

{


string message = "Гражданин не будет призван на срочную службу";

Console.WriteLine("Введите возраст гражданина");

byte age = byte.Parse(Console.ReadLine());

if (age >= 18)

{

if (age < 30)

{

Console.WriteLine("Введите количество детей");

byte children = byte.Parse(Console.ReadLine());

if (children < 2)

{

Console.WriteLine("Гражданин будет призван на срочную службу");

}

else

{

Console.WriteLine(message + ". Дети");

}

}

else

{

Console.WriteLine(message + ". Старше 30");

}

}

else

{

Console.WriteLine(message + ". Моложе 18");

}

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

В заключении.

Для решения задач с независящими друг от друга условиями, применяйте расширенную форму if … else if … else, которую можно представить, как нумерованный список.

вложенные друг в друга, конструкции с классической формой if…else.

Для решения задач с зависящими условиями, применяйте вложенные друг в друга, конструкции с классической формой if…else. Можно представить, как нумерованный список с подпунктами.

На этом занятие закончено.

Вы можете самостоятельно найти задачи для закрепления теоретического материала или для получения задач с ответами отправьте письмо на basicprog@mail.ru

Удачи в выполнении практических заданий!

Показать полностью 1
2

ВЕТВЛЕНИЕ и bool. Синтаксис C#

Из этой лекции вы узнаете о базовой структуре структурного программирования — ветвлении и логическом типе данных bool.

Ветвление — это одна из базовых структур структурного программирования, позволяющая пользователю решать задачи с неопределенными условиями, к примеру, получить ответ от компьютера на заданный вопрос. Структура «ветвления» является вложенной структурой в структуру следования и на алгоритмической блок-схеме представлена как разветвляющийся алгоритм.

Операция ветвления — это операция выбора выполнения программного кода в зависимости от выполнения или невыполнения какого-то условия. Эту операцию можно представить как ответ на некоторый вопрос, который подразумевает один из ответов. Либо — да, либо — нет. Именно этот ответ создает иллюзорную видимость интеллекта вычислительной системы. В зависимости от полученного ответа выполняется заранее определенный программный код.

В операциях ветвления используются операции отношения, содержащие операторы сравнения и равенства.

Операторы сравнения

>  строго больше

<=  меньше или равно

<  строго меньше

>= больше или равно

Операторы равенства

= =  равно

!=  не равно

Все операторы интуитивно понятны. Из-за того, что оператор « = » является оператором присваивания, то для операции « равно » используется оператор « = = ».

Тут нужно указать, что операция равенства делится на две операции — равенство и строгое равенство. В C#, операция строго равенства выполняется с помощью метода Equals(). О ней мы расскажем позже.

Операция ветвления состоит из двух этапов. Вычисление условия и переход на выбранную ветку программного кода.

Вычисление условия — это логическая операция, состоящая из операции отношения. Результатом операции отношения является одно из двух логических значений либо true, либо false — ответ на вопрос, либо да, либо нет. Для хранения результата используется тип данных — bool.

Тип данных bool относится к примитивным типам данных, хранится в стеке и имеет размер 8 бит. В отличие от других типов данных, хранимые значения определены заранее — это либо true, истинность, либо false, ложь.

static void Main(string[] args)

{

bool a = true;

bool b = false;

}

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

static void Main(string[] args)

{

int x = 1;

bool a = x < 2;

bool b = 1 > 2;

Console.WriteLine("A = " + a + " B = " + b);

}

Для выбора блока исполняемого кода используется конструкция с оператором — if. Эта конструкция имеет множество форм, классической из которых является форма if … else (если…иначе).

Оператор if выполняет вычисление логического выражения и в случае результата «true», выполняет программный код своего блока. В случае результате «false», выполняется программный в блоке оператора — else.

Напишем программу проверки на положительное число.

static void Main(string[] args)

{

int number = 2;

bool compare;

compare = 0 < number;

if (compare)

{

Console.WriteLine("Число положительное");

}

else

{

Console.WriteLine("Число отрицательное");

}

}

Помимо вывода сообщений, соответствующие блоки могут содержать программный код.

Программа для извлечения квадратного корня. Так как корень нельзя извлекать из отрицательного числа, производится проверка числа на положительное.

static void Main(string[] args)

{

int number = -2;

if (0 < number)

{

double sqr = Math.Sqrt(number);

sqr = Math.Round(sqr, 2);

Console.WriteLine("Корень числа: " + number + " = " + sqr);

}

else

{

Console.WriteLine("Число не является положительным");

}

}

Забежим вперед и используя генератор случайных чисел напишем игру «Угадай число»

static void Main(string[] args)

{

Random rnd = new Random();

int value = rnd.Next(1, 3);

Console.WriteLine("Введите число от одного до трех");

int number = int.Parse(Console.ReadLine());

if (value == number)

{

Console.WriteLine("Вы выиграли");

}

else

{

Console.WriteLine("Вы проиграли");

}

}

Здесь, в строке int value = rnd.Next(1, 3);, генерируется случайное число в диапазоне от одного до трех, которое затем сравнивается с введенным числом

В заключении.

Для решения задач с неопределенными условиями, используются операции отношения. Результат вычисления операции отношения, принимает два значения — true и false и хранятся в переменных с типом данных —bool. Операции отношения используются в программах с базовыми структурами структурного программирования — ветвление и повторение.

Одной из конструкций ветвления является конструкция if…else. Оператор if выполняет операцию по вычислению операции отношения и в зависимости от полученного результата, выполняется либо блок программного кода относящегося к оператору « if», либо блок кода оператора «else»

На этом занятие закончено.

Вы можете самостоятельно найти задачи для закрепления теоретического материала или для получения задач с ответами отправьте письмо на basicprog@mail.ru

Удачи в выполнении практических заданий!

Показать полностью

Проверка знаний о значениях. Синтаксис C#

Напишите программу расчета кредитной ставки для заемщика.

Программа должна запрашивать с клавиатуры следующие данные

  • Фамилию и имя заемщика

  • Возраст заемщика

  • Заработная плата заемщика

  • Трудовой стаж заемщика

  • Требуемая сумма кредита

  • Коммунальные расходы в месяц

  • Другие расходы

  • Первоначальная ставка по кредиту. К примеру, ставка ЦБ РФ.

Пример ввода:

  • Фамилия и имя заемщика — Иванов Иван

  • Возраст заемщика — 45

  • Заработная плата заемщика — 150000

  • Трудовой стаж заемщика—30

  • Требуемая сумма кредита—1000000

  • Коммунальные расходы в месяц—5000

  • Другие расходы—10000

  • Первоначальная ставка по кредиту—16

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

  • Рассчитайте коэффициент возраста. Для этого —Трудовой стаж /Возраст. Округлите результат до второго знака после запятой.

  • Рассчитайте коэффициент заработной платы по следующей формуле — 1000*(Базовая ставка – ((Заработная плата * Базовая ставка)/ (Заработная плата + Базовая ставка))). Округлите результат до второго знака после запятой.

  • Вычислите конечную ставку кредита по формуле— (Базовая ставка – коэффициент возраста заемщика – коэффициент заработной платы). Преобразуйте полученный результат в целое число с наилучшим типом данных.

  • Рассчитайте по формуле период погашения кредита в полных месяцах — (Сумма кредита * конечную ставку)/ (Заработная плата – коммунальные расходы – другие расходы).

Вывод должен содержать следующую информацию

  • Фамилия, имя заемщика в одну строку

  • Сумма кредита

  • Ставка по кредиту конечная

  • Период погашения в полных месяцах

Пример вывода

  • Фамилия, имя заемщика— Иванов Иван

  • Сумма кредита—1000000 руб.

  • Ставка по кредиту конечная—14%

  • Период погашения в полных месяцах—104 мес.

Для получения возможного решения отправьте письмо на basicprog@mail.ru

Удачи в выполнении практических заданий!

Показать полностью
4

Преобразование типов

Из этой лекции вы узнаете, об особенностях применения неявного типа var и о преобразовании типов данных.

Начнем эту лекцию с написания программы подсчета населения двух стран Индии и Китая. Для инициализации переменных будем использовать неявный тип данных — var, который не рекомендуется применять на начальном этапе обучения.

Неявный тип данных var — это операция, при которой тип данных переменной назначается по формату записи значения. Это свойство не позволяет объявить переменную, поэтому переменная с типом данных var инициализируется.

Напомним соответствие формата записи и типа данных. Значения, состоящего из цифр —тип данных int, для чисел с точкой— double, набор любых символов заключенных в двойные кавычки — string.

static void Main(string[] args)

{

var text = "Высота Эйфелевой башни ";

var number = 328;

Console.WriteLine(text + number + " метров");

}

Применение var удобно, но в процессе написания кода, во избежание непредсказуемых результатом из-за несовместимости различных типов данных, необходимо контролировать тип данных у переменных.

Для определения типа данных у переменной применяется метод GetType(), который  выводит на экран тип данных с классом которому принадлежит этот тип, и его аналог GetTypeCode(), который показывает тип данных без принадлежности к классу. Для просмотра типа данных достаточно поставить точку после переменной и написать имя метода, точечная нотация. Не забываем формат метода — две круглые скобки в конце названия.

static void Main(string[] args)

{

var text = "Высота Эйфелевой башни ";

var number = 328;

Console.WriteLine(text + number + " метров");

Console.WriteLine("Тип данных text- " + text.GetTypeCode());

Console.WriteLine("Тип данных number- " + number.GetTypeCode());

}

В этой программе есть один недостаток, а именно переменной number, которой VS автоматически назначила тип данных int, что создает не нужную нагрузку на аппаратную часть. Здесь больше подойдет тип данных ushort.

Так как тип данных var определяет назначаемый тип по присваиваемому значению, то достаточно явно изменить тип этого значения.

static void Main(string[] args)

{

var text = "Высота Эйфелевой башни ";

var number = (ushort)328;

Console.WriteLine(text + number + " метров");

Console.WriteLine("Тип данных text- " + text.GetTypeCode());

Console.WriteLine("Тип данных number- " + number.GetTypeCode());

}

Операция по явному изменению типа данных называется — явное привидение типов или преобразование типов.

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

static void Main(string[] args)

{

var day1 = -3.1;

var day2 = 1.2;

var day3 = 5.5;

var result = (int) ((day1 + day2 + day3) / 3);

Console.WriteLine("Средняя температура: " + result);

}

Или снизить разрядность переменной с 32 ячеек до 8.

static void Main(string[] args)

{

var day1 = -3.1;

var day2 = 1.2;

var day3 = 5.5;

var result = (byte)((day1 + day2 + day3) / 3);

Console.WriteLine("Средняя температура: " + result);

Console.WriteLine("Тип данных: " + result.GetTypeCode());

}

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

static void Main(string[] args)

{

double day1 = -3.1;

double day2 = 1.2;

double day3 = 5.5;

byte result = (byte)((day1 + day2 + day3) / 3);

Console.WriteLine("Средняя температура: " + result);

Console.WriteLine("Тип данных: " + result.GetTypeCode());

}

Еще одно применение преобразование нашло в учебном вводе с клавиатуры. Почему в учебном расскажем ниже

Для ввода информации будем использовать метод ReadLine. Вызов метода аналогичен вызову метода WriteLine. По правилам хорошего тона, перед вводом, пишется строка приглашение, иначе как понять мигающий курсор.

static void Main(string[] args)

{

Console.WriteLine("Введите Ваш текст. По окончанию нажмите enter");

string text = Console.ReadLine();

Console.Clear();

Console.WriteLine("Вы ввели следующий текст: " + text);

}

Поздравляем! Вы создали первую диалоговую программу, а Пользователь получил в свое распоряжение программный интерфейс для управления ходом вычислений.

Перезапустим программу и сделаем немыслимое — введем числовое значение, которым будет инициализирована переменная с типом данных string. Но ошибки не последовало, и программа вывела на экран число.

Возникает вопрос, как числовое значение поместилось в область памяти, предназначенное для строковых значений. Ответ - никак. Метод Console.ReadLine(); принимает на вход набор символов. Введённое нами число было принято, как строка и передано в строковую переменную как строка, и на экране мы видим не число, но слово (строку) в виде числа.

Для инициализации переменной типом данных отличным от типа данных string требуется явное преобразование типа данных.

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

Попробуйте инициализировать переменную с типом данных int, значением, содержащим символ отличным от цифры, а метод Console.ReadLine() именно инициализирует строку вводимым значением. К ошибке приведет даже неверный выбор точки или запятой в значении переменной с типом данных double.

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

Преобразуем строку состоящую из цифр в полноценное числовое значение

static void Main(string[] args)

{

Console.WriteLine("Введите число");

int number = int.Parse(Console.ReadLine());

Console.Clear();

Console.WriteLine("Вы ввели число: " + number);

}

Для преобразования типа данных используется следующая конструкция преобразования типа данных string в тип данных int— int.Parse(Console.ReadLine()). Для byte, соответственно это будет byte.Parse(), для short — short.Parse() и т.д.  

Пример программы с различными типами данных

static void Main(string[] args)

{

Console.WriteLine("Введите ваше имя. Нажмите enter");

string text = Console.ReadLine();

Console.WriteLine("Введите ваш возраст. Нажмите enter");

int numberInt = int.Parse(Console.ReadLine());

Console.WriteLine("Введите число Pi до 5 знака после запятой. Нажмите enter");

double numberDouble = double.Parse(Console.ReadLine());

Console.Clear();

Console.WriteLine("Ваше имя: " + text);

Console.WriteLine("Ваш возраст: " + numberInt);

Console.WriteLine("Число Pi: " + numberDouble);

}

В заключении.

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

На этом занятие закончено.

Вы можете самостоятельно найти задачи для закрепления теоретического материала или для получения задач с ответами отправьте письмо на basicprog@mail.ru

Удачи в выполнении практических заданий!

Показать полностью
1

Особенности применения чисел с плавающей точкой

Особенности применения чисел с плавающей точкой.

Тема чисел с плавающей точкой достаточна сложна. Исходя из принципа: польза — вред, суть представления чисел с плавающей точкой будет опущена и речь в лекции пойдет об особенностях применения таких чисел. Автор считает, что на начальном этапе обучения, знания об операциях чисел с плавающей точкой на аппаратном уровне, не принесут практической пользы.

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

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

Типы с плавающей запятой (float, double)

float: хранит число с плавающей точкой от -1.5*10-45 до 3.4*1038 и занимает 4 байта. Формат значения для float — в конце операнда-значения указывается суффикс « f »

double: хранит число с плавающей точкой от ±5.0*10-324 до ±1.7*10308 и занимает 8 байта. Формат для double  — операнд-значение записывается с указанием дробной части, если дробная часть равно нулю, то указывается ноль.

Отдельно стоит тип данных —decimal, который хранит число с плавающей точкой от ±1.0*10-28 до ±7.9*1028 и занимает 16 байта. Формат для decimal — в конце операнда-значения указывается суффикс «M». Операции с типом данных рассмотрены не будут.

Типы данных для вещественных чисел, так же, как и для целых относятся к примитивным типам данных, хранятся в стеке и обладают теми же особенностями применения, что и целочисленные значения. Использование float, за счет небольшого размера, позволяет эффективно использовать аппаратные ресурсы вычислительной системы в ущерб точности, double позволяет достичь более высокой точности, но занимает 8 байт.

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

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

Пример 1. Формат значения

Напишем программу деления целочисленного числа 10 на целочисленное число 6.

static void Main(string[] args)

{

double variable = 10/6;

Console.WriteLine("Десять разделить на шесть = " + variable);

}

Несмотря на то, что в памяти компьютера было выделено место для записи значения с плавающей точкой, в переменную variable было записана только целая часть полученного результата. Объяснение этому кроется в формате полученного результата от операции деления целого числа на целое. Результатом такой операции всегда будет значение с автоматически присвоенным типом данных int, который не предназначен для хранения значения с дробной частью, поэтому дробная часть была отброшена, и в переменную с типом данных double, именем variable, была записана только целая часть. 

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

static void Main(string[] args)

{

double variable = 10 / 6.0;

Console.WriteLine("Десять разделить на шесть = " + variable);

}

Пример 2. Округление

Не всегда есть необходимость большой точности. Так, результату финансовых вычислений вполне удовлетворит точность с двумя знаками после запятой. Для округления используется метод Round(), в круглые скобки которого помещается имя переменной, а через запятую указывается количество знаков после запятой. Для хранения результата округления используется тип данных — double. В отличии от метода WriteLine(), который принадлежит классу Console, метод  Round() принадлежит классу Math, поэтому для вызова метода, используется конструкция  Math.Round().

static void Main(string[] args)

{

float weight = 1.3f;

float price = 5.22f;

double total = Math.Round(weight * price, 2);

Console.WriteLine("Сумма = " + total);

}

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

3. Операции над переменными

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

static void Main(string[] args)

{

float a = 1.2f;

float b = 1.2f;

float sumFloat = a + b;

double sumDouble = a + b;

Console.WriteLine("sumFloat = " + sumFloat);

Console.WriteLine("sumDouble = " + sumDouble);

}

5. Ограничение по размеру выделяемой области памяти

При операциях над числами с плавающей точкой необходимо помнить, что дробная часть сокращается в угоду целой части. Если вы хотите использовать число Pi для точных расчетов, используйте тип данных double.

static void Main(string[] args)

{

float floatPi = 3.14159265358980f;

double  doublePi = 3.14159265358980;

Console.WriteLine("Тип данных float = " + floatPi);

Console.WriteLine("Тип данных double = " + doublePi);

}

В заключение.

Числа с плавающей точкой хранятся в стеке и относятся к примитивным типам данных. Из-за особенностей хранения чисел с плавающей точкой, применение на практике таких чисел довольно часто преподносят неожиданные результата. Большая часть ошибок приходится на использование не идентичных типов данных. Возьмите за правило перепроверять каждый результат таких операций.

На этом занятие закончено.

Вы можете самостоятельно найти задачи для закрепления теоретического материала или для получения задач с ответами отправьте письмо на basicprog@mail.ru

Удачи в выполнении практических заданий!

Показать полностью
3

Особенности использования целочисленных значений

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

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

Ниже приведен список типов данных для хранения целых чисел:

byte: хранит целое число от 0 до 255 и занимает 1 байт.

short: хранит целое число от -32768 до 32767 и занимает 2 байта.

ushort, хранит целое число от 0 до 65 535 и занимает 2 байта.

int: хранит целое число от -2147483648 до 2147483647 и занимает 4 байта.

uint: хранит целое число от 0 до 4294967295 и занимает 4 байта

long: хранит целое число от –9 223 372 036 854 775 808 до 9 223 372 036 854 775 807 и занимает 8 байт.

Возникает вопрос. Для чего необходимо такое количество типов данных для хранения целочисленных значений?

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

На момент написания статьи, максимальная продолжительность жизни составила 122 года. Давайте посмотрим, как двоичная запись числа 122 будет выглядеть в переменных с различными типами данных. Так как, возраст не может быть отрицательным, то для хранения значения возраста, выберем тип данных для хранения положительного числа.

Тип данных byte. Может хранить любой целое число от 0 до 255 и занимает 1 байт(8 бит)

Тип данных uint. Целое число от 0 до 4294967295, занимает 4 байта(32 бит)

Как видим, оба типа данных подходят для хранения возраста человека. Однако если оценить эффективность использования аппаратных ресурсов тип данных byte предпочтительней, в то время как тип данных uint избыточен.

Наглядно видно, что для переменной с типом данных uint выделен блок из ячеек размером 4 байта или 32 ячейки. Что в этом плохого? Под переменную выделено 32 ячейки, поэтому, все 32 ячейки памяти будут учувствовать во всех операциях, производимых с этой переменной. На инициализацию, хранение и обработку всех 32 ячеек, в том числе и на неиспользуемые 24 разряда, будут тратится аппаратные ресурсы вычислительной системы. Еще одним минусом, является размер занимаемой памяти. Так размер занимаемой памяти для хранения данных возраста одной тысячи человек в случае с типом данных byte будет занимать 1000чел Х 8 бит= 8000 бит—один килобайт памяти, а с типом данных uint —4 кБ, т.е. в четыре раза больше.

Возникает вопрос, почему столь эффективный, с аппаратной стороны, тип данных byte не использовать повсеместно. Для чего нужны остальные типы данных?

Для ответа на этот вопрос, напишем программу подсчета общей продолжительности жизни трех долгожителей, которым больше 100 лет.

Здесь нужно указать на одну из особенностей VS. Конструкция операции присвоения значения состоит из левого операнда-переменной и правого операнда значения, где левому операнду-переменной тип данных указывается явно, а характеристики правого операнда определяются по формату записи. Однако результату арифметических операциях, когда, к примеру складываются два числа, VS автоматически назначает тип данных — int.

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

Явное привидение —операция, когда операнду-значению явно указывается тип данных. Для этого достаточно в операнде-значении указать в скобках какой тип нужен. О преобразовании типов будет отдельная лекция.

static void Main(string[] args)

{

byte age1 = 122;

byte age2 = 102;

byte age3 = 120;

byte sumByte = (byte)(age1 + age2 + age3);

Console.WriteLine("Запись числа 344 в переменную sumByte = " + sumByte);

int sumInt = age1 + age2 + age3;

Console.WriteLine("Запись числа 344 в переменную sumInt = " + sumInt);

}

В строке: byte sumByte = (byte)(age1 + age2 + age3); применена операция по преобразование типов — явное привидение типа данных.

Запустим программу. И видим у переменной « sumByte »  с типом данных « byte » очень неожиданный результат.

Результатом операции сложения: 122 + 102 + 120, будет число 344, которое записывается в переменную sumByte, с явным привидением изменением с автоматического типа int на тип данных byte. Число 344 выходит за рамки диапазона типа данных byte, поэтому была сохранена только часть значения.

Визуальное представление хранения числа 344 в переменных sumByte и sumInt

Визуально видно, что для записи числа 344 требуется 9 ячеек памяти.

Мы же, явным привидением типов (byte)(age1 + age2 + age3); отменили неявное автоматическое преобразование результата сложения и вместо типа данных int

операнд- справа получил тип данных byte. Восьми конденсаторов, ячеек памяти, физически не хватило для размещения числа 344.

В случае с переменной « sumInt », VS по умолчанию указала для результата сложения тип данных int, который имеет 32 разряда и может хранить числа в диапазоне от -2147483648 до 2147483647.

Однако тип данных int не оптимален для данной программы. Так int хранит как положительные, так и отрицательные числа, а при учете возраста отрицательных чисел быть не может, оптимальным типом в данном случае является тип данных uint, который хранит положительные целые числа в диапазоне от 0 до 4294967295.

У вас, наверное, возник вопрос: «Как тип данных «int» занимает 4 байта и хранить числа в диапазоне от -2147483648 до 2147483647, а «uint» в тех же 4 байтах хранит число в диапазоне от 0 до 4294967295»?

Все очень просто. В случае с «int», старший, 32 разряд, выделяется под указание положительное или отрицательное значение будет хранится. Ноль в 32 разряде указывает, что число положительное, а единица — отрицательное. Таким образом для хранения числа остается только 31 разряд, что и соответствует диапазону хранимого значения.

В заключении.

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

На этом занятие закончено.

Вы можете самостоятельно найти задачи для закрепления теоретического материала или для получения задач с ответами отправьте письмо на basicprog@mail.ru

Удачи в выполнении практических заданий!

Показать полностью 3

Значения в памяти компьютера

Из этой лекции вы узнаете, как хранятся значения.

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

Для хранения значения, в операционном запоминающем устройстве (ОЗУ) компьютера, выделяется некоторая область, состоящая из элементов памяти. Каждый такой элемент представляет собой электронный компонент содержащий конденсатор.

Конденсатор имеет свойства удерживать электрический заряд, т.е. находится в двух состояниях заражено или разряжено. Эту особенность конденсатора можно описать двоичной системой, где 1 — заряжено, 0— разряжено. Таким образом в распоряжении программиста оказывается, электронный программируемый прибор, который может хранить либо ноль, либо единицу, что является самой маленькой единицей данных — бит.

В памяти компьютера конденсаторы группируются по восемь штук. Такая группа называется адресная ячейка. Адресная ячейка — это ячейка памяти с автоматически назначенным адресом вида 0x7fffa40c5fac. При написании кода, подменяется удобочитаемым и информативным именем переменной. К примеру, string text, где имя text подменяет автоматически присвоенный адрес.

Размер адресной ячейки составляет 8 бит или один байт Адресная ячейка способна хранить целочисленное значение от 0 до 255. Сами адресные ячейки так же могут группироваться в блоки, вплоть до 64 конденсаторов или 64 бита или 8 байт. Такие блоки могут хранить гигантские числа. К примеру, размер известного типа данных int равен 4 байта и может хранить число равное приблизительно 4,5 миллиарда.

Для наглядного представления возьмите листочек или тетрадь в клеточку, развивайте мелкую моторику, я же буду использовать таблицу Excel.

Представим, что лист — это память компьютера, где каждая клеточка — это элемент памяти, которая содержит электронный компонент — конденсатор.

Запустим VS и объявим переменную для хранения числового значения

static void Main(string[] args)

{

byte number;

}

Здесь тип данных byte указывает на выделение в памяти компьютера блока из восьми элементов, поэтому, на тетрадном листке выделите блок из восьми клеточек и пронумеруйте их. Будем считать, что каждая клеточка — это элемент памяти, содержащий конденсатор.

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

Запишем в переменную значение, в виде числа 120.

static void Main(string[] args)

{

byte number;

number = 120;

}

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

Так как для удобства описания состояния конденсатора используется двоичная система, то воспользуемся этим свойством и добавим, как выглядит число 120 в двоичной системе.

Визуально видно, для хранения числа 120 в выделенном области памяти необходимо сохранить заряд в элементах (конденсаторах) находящихся в позиции 7, 6, 5, 3, 2.

Таким образом за счет свойства конденсатора— заряжено-разряжено в памяти компьютера сохранено значение в виде числа. Числовые значения представляют собой единый неделимый элемент, который хранится в стеке памяти, что обеспечивает быстрый доступ к значению числового типа. Значения хранимые в стеке относятся к примитивным типам данных.

Совершенно по-другому хранится строковое значение. Так как в памяти компьютера могут хранится только числа в двоичной системе, а строковое значение состоит из букв, символов, то для хранения строкового значения в памяти компьютера используется следующий механизм. Строковое значение разбивается на отдельные буквы, символы, где каждому символу сопоставлено числовое значение. Информация о соответствии символа и его числового значения отражена в таблице ASCII.

После того как символы строки преобразованы в массив отдельных числовых значений, этот массив помещается для хранения в особую область памяти — куча, а в стеке, для доступа к этому массиву, создается ссылка с именем, что и дало название таким типам данных — ссылочные типы данных.  Имя ссылки указывает не на само строковое значение, а на числовое значение, в котором хранится информация, где в куче искать строковое значение.

Для примера возьмем имя основателя компании Microsoft - Bill. Этот объект состоит не из чисел, но из символов отличных от чисел.  Для хранения значения Bill разделим объект-строку на отдельные элементы в виде объект-число. В данном случае это буквы —B, i, l, l и в соответствии с таблицей ASCII, строка будет выглядеть как набор отдельных элементов числовых значений — 66 105 108 108.

После преобразования, значения Bill в числовые значения 66, 105, 108, 108, эти элементы - числа записываются в памяти компьютера — куча.

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

Ссылка хранится в стеке и имеет имя. По имени вы обращаетесь к ссылке, которая перенаправляет вас к нужному значению в куче. Ссылка 32 бита.

Хранение элементов в куче

Так как строковое значение представлено набором элементов, то мы можем обратится к каждому элементу в отдельности. Помятую, что имя указывает на ссылку, а ссылка перенаправляет к значению, для доступа к элементу используется следующая конструкция — имя ссылки[индекс элемента], где индекс элемента — номер хранения элемента в значении. Нумерация элементов начинается не с единицы, но с нуля.

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

static void Main(string[] args)

{

string text = "Bill";

Console.WriteLine("Вторая элемент значения  -  " + text[1]);

}

Конструкция — text[1], отдает команду на вывод содержимого одного из элементов переменной « text »  с индексом « 1 ».  Вывод на экран одного элемента значения свидетельствует о раздельном хранении его элементов.

В заключении.

Хранение значение происходит в адресных ячейках состоящих из восьми элементов, каждый из которых содержит конденсатор. Хранение описывается с помощью двоичной системы. Разделяют хранение в стеке — примитивные типы данных и в куче — ссылочные типы данных.

Зная, как хранятся значения в памяти компьютера дадим определение переменной.

Переменная — именованная область памяти, выделенная в памяти компьютера для хранения изменяемого значения с определенными характеристиками.

Под выделенной областью памяти понимается блок из ячеек (контейнер), выделенный из общего пространства оперативного запоминающего устройства (память компьютера), доступ к которому осуществляется по присвоенному имени. На самом деле доступ осуществляется по назначенному адресу вида — 0x7fffa40c5fac, но такой адрес трудночитаем и подменяется более информативным именем переменной вида — number.

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

На этом занятие закончено.

Вы можете самостоятельно найти задачи для закрепления теоретического материала или написать — basicprog@mail.ru.

Удачи в выполнении практических заданий!

Показать полностью 6
Отличная работа, все прочитано!