×
Ви дійсно бажаєте відкрити доступ до тестування за курсом C# 5.0 Стартовый на 40 днів?
ВІДЕОУРОК № 2. Машинная математика и системы счисления
Здравствуйте! Тема нашего сегодняшнего урока: «Машинная математика и системы счисления». На протяжении сегодняшнего урока мы с вами будем рассматривать такие понятия как двоичная и шестнадцатеричная системы счисления. Хочу заметить, что мы – люди в повседневной жизни используем десятичную систему счисления. Почему десятичную? Потому что у нас только десять цифр для записи числа. А машина пользуется только двумя цифрами, если у нас цифры от 0 до 9, то у машины от 0 до 1. А шестнадцатеричная система? Это тоже интересная система, которая представляет собой некий мост между машиной и человеком. Мы это тоже разберем с вами. Далее мы разберем с вами такие понятия, очень важные понятия, как переменные и тип данных, который может хранится в это переменной. Итак, мы с вами сегодня должны разобрать двоичную и шестнадцатеричную системы счисления, понять первую конструкцию языка C# - переменную и типы данных которые могут хранится в этой переменной. Но сначала мы с вами должны немножко поговорить о машине. Об электронно-вычислительной машине. Совсем немного. И рассмотреть такие важные физические части ее как ОЗУ и немножко процессор. Почему ОЗУ? Зачем рассматривать ОЗУ? Потому что в ОЗУ, в быстрой памяти наша программы находятся сами и хранят там свои данные.
А мы с вами перейдем к делу и перейдем к нашему уроку. И начнем мы с вами с такого понятия как бит. Я думаю, что все слышали такие понятия как байт и бит. Это уже достаточно распространенный понятия в нашем современном мире. Бит. Можно сказать, что это некая единица для представления информации. Так вот, в наших вычислительных машинах бит может иметь только два состояния. Обычно, в электронике биты представлены такими сложными конструкциями как триггеры, но не пугайтесь, мы не будем рассматривать триггеры. Мы рассмотрим это на более примитивных вещах, потому что какая разница на каких жизненных сущностях нам представлять эти два состояния. Мы можем сказать, что наша лампочка может иметь два состояния. Она горит и не горит. Можно сказать, что это бит, который имеет два состояния. Давайте посмотрим, чтобы нам заменить триггер, мы возьмем и заменим его просто простой лампочкой. И мы понимаем, что лампочка может иметь два состояния: гореть и не гореть. Но правильно ли это будет? Правильное ли это представление состояний, так ли это в самой машине? Не совсем так. А давайте посмотрим как у нас в машине это происходит. Обратите внимание, кода лампочка не горит, мы будем считать, что машина не работает, она выключена, а когда лампочка горит в пол накала, мы будем кодировать это состояние нулем. Но если нам будет нужно записать комбинацию состояний лампочек на бумаге, не будем же каждый раз рисовать себе лампочки. Я выработаю какую-то символику. В данном случае мы используем 0 и 1 для представления этих состояний и когда лампочка будем мигать. Я этой лампочкой хочу представить азбуку Морзе. Точка, тире, точка, точка, тире. Точка – ноль. Тире – 1. И теперь мы будем считать, что в настоящей машине если лампочка не горит, то наша машина выключена, если лампочка горит в пол накала, то это будет 0, если лампочка горит в полный накал, то это будет 1. И даже мы люди можем это различать.
Представьте себе, что вы позволите мне вами командовать. Давайте мы сделаем так. Я беру у вас в квартире, напротив вас на стене вкручиваю лампочку, делаю такую панельку, такую черную планочку прибиваю. Туда вкручиваю лампочку и говорю: «Запомните, если лампочка горит в пол накала – вы идете и едите яблоко. Если лампочка горит в полный накал вы идете и ложитесь спать.» Все теперь у вас есть две команды: идти покушать, и лечь спать. Но если я хочу вам дать больше двух команд. Вам покажется что это игра с лампочками. Это сложно, придётся вкручивать новые лампочки. Давайте посмотрим. На самом деле это не сложно. Главное держите в голове перед собой вашу стену, планку с одной лампочкой и две команды: пойти покушать и лечь спать. Давайте перейдем к следующему слайду. Значит, смотрим. На этом слайде у нас показан бит. То есть его представление в виде лампочки, в которой два состояния: 0 и 1. Если у вас загорается лампочка в пол накала, то вы идете и едите яблоко если загорается в полный накал – едите грушу. Например, я диетолог и я вам постоянно рекомендую, что вам нужно есть. Но у нас же много других фруктов. Я хочу попросить, чтобы вы съели, например, сливу и ананас. Что надо здесь сделать? Нужна еще одна лампочка. Давайте посмотрим, а если мы вкручиваем в стену две лампочки. Я говорю, если у вас горит две лампочки в пол накала (00) – вы едите яблоко, если первая горит в пол накала, другая в полный накал (01) – вы идете едите грушу. Если левая лампочка будет 1, а правая лампочка будет 0 – вы едите сливу. Если две лампочки горят в полный накал – вы едите ананас. Я хочу еще больше команд давать. Что вы мне посоветуете? Еще одну лампочку? Хорошо. Обратите внимание, теперь мы видим, что мы тремя битами кодируем 8 команд. Давайте вернемся на первый слайд. Если у нас одна лампочка, то мы кодируем 2 команды или 2 числа. Двумя лампочками можно представить 4 команды или 4 числа. Вот их все возможные комбинации. Тремя лампочками можно представить 8 команд или 8 чисел. По сути, это без разницы какие команды мы даем. А давайте я вкручу вам две панели. На правой панели будут идти команды: иди, смотри телевизор. А на левой панели у меня будут коды того что вы хотите, например, что именно вы хотите есть или какой номер программы будете смотреть. То есть одна панель будет только для команд, а вторая панель будет только для данных. Заметьте, вы, как процессор, с правой панели получаете команды и для этих команд вы используете с левой панели данные. И вы берете команды, берете данные и в итоге выполняете некую полноценную операцию. Но мы возвращаемся к нашим битам. Значит тремя лампочками мы можем дать 8 команд, но это мало для человека. Что вы мне советуете? Еще лампочку вкрутить. Обратите внимание, 4 лампочки. Четырьмя лампочками мы можем представить 16 команд. Вы это можете поэкспериментировать сами. Взять либо на листочке переписать себе все эти комбинации. Это просто. Я бы даже вам советовал это сделать, потому что раньше такие таблицы все программисты писали, которые учились. 5 лампочек – 32 команды или 32 числа мы можем представить вот такой серией лампочек. 6 бит – 64 команды. 7 бит – 128 команд. Восемь бит – 256 команд. Слышали, число 256 – любимое число программистов. Вот, это максимальное количество команд, которые мы можем закодировать 8 лампочками. А почему мы берем 8 лампочек. Это очень просто. Потому что наш байт, он и представляет собой такой некий ящик, в который вкручено 8 лампочек, от которого идут проводки. Это, конечно, очень грубо, это очень вульгарно-прямолинейно. Я понимаю, что если меня слушают электронщики, то они конечно видят здесь не лампочки, а триггеры. Но нам простым обывателям достаточно представить себе лампочки, которые могут иметь два, различимых человеком, состояния. Это лампочка горит тускло, то есть в пол накала, а это ярко – в полный накал. Я думаю, что столько состояний нормальный человек в состоянии различить. И теперь мы смотрим, что на этом слайде мы представляем восьмибитовый элемент, который принято называть байтом. Как вы видите, байт- это единица хранения и обработки цифровой информации в вычислительно машине. Мы не можем отдельно в вычислительной технике воспользоваться одним битом. Он не лежит отдельно, он находится только в контексте такого ящика, называемого байтом. А какие к нас еще есть единицы измерения количества информации в информатике. Давайте посмотрим. 1 килобайт – это 1024 байта, 1024 ящика, стоящих рядом. Это много. Но нет, это не много. В 1 Мегабайте – 1024 Кбайта. То есть 1024*1024, это будет больше миллиона таких ящиков. А Гигабайт, это мы берем 1024*1024*1024. Вы представляете сколько это. Это уже больше миллиарда. 1 Терабайт = 1024*1024*1024*1024. Это очень много, вы видите какие объёмы информации могут содержать в себе современные вычислительные устройства. Например, жесткие диски размером в несколько Терабайт. Вы представляете сколько там хранится информации и какая у них плотность. А вы представляете свое ОЗУ, когда вы покупаете компьютер, у вас в компьютере, допустим, 16 ГБ, нет мы скажем даже одной планкой даже 4 ГБ. Там больше 4 миллиардов ящиков электронщики туда засунули. Представляете? Да, это сложно представить.
Давайте перейдем на следующий слайд. Обратите внимание, знакомая всем планка ОЗУ – оперативно-запоминающее устройство. Мы, частенько, чтобы сделать наш компьютер быстрее, чтобы добавить ему памяти, покупаем ему такие планки и вставляем ему в материнскую плату в специальный слот внутри системного блока. Видите эти черные микросхемы? Нет, это не байт. Это контейнеры, которые в себе содержат множество таких байтов. И если эта планка будет 4 ГБ, например, вы представляете, что по вот этим контейнерам распределены вот эти байты. Представляете, как это много. И если мы заглянем под микроскопом, ну это тоже сказано вульгарно-прямолинейно и очень грубо, то мы увидим внутри этих микросхем такие ящики с лампочками. И мы понимаем теперь что вся информация будет кодироваться именно таким способом. Один байт группирует в себе 8 битов. Каждый бит в нас пронумерован. Видите, у нас здесь нанесены номера. Но скажу еще больше, каждый байт имеет на себе табличку с номером. Представляете, каждый бит пронумерован, и каждый байт имеет свой уникальный номер, уникальный адрес, так называемый, адрес в памяти. Подведем итог. Если размер ОЗУ = 1ГБ, то в нем имеется 1073741824 Байта. Это очень много. Каждый байт в памяти имеет свой адрес. На каждом ящике есть такая табличка с таким номером. Самый первый байт у нас нумеруется с нулю, за ним идет второй с адресом 1. Адрес предпоследнего 1073741822, а последнего 1073741823. Вы представляете сколько в такой планке ящиков. Микроэлектроника.
Далее. Обратите внимание. Процессор! Мы знаем, что процессор всегда взаимодействует с ОЗУ. Что же он делает? Давайте заглянем одним глазом внутрь процессора. Оказывается, процессор состоит из таких же байтов. Только они не имеют таких номеров как в ОЗУ. Они не нумеруются от 0 и дальше. У них есть свои уникальные имена. Например, AX, BX, CX, DX. Вот идут свои специальные регистры. И что же делает процессор. Он обращается к ОЗУ и берет в себя определенные данные. Мы пока не будем говорить о кодах программы, мы пока будем говорить только о данных, которые находятся в ОЗУ. И получается, что если мы хотим сложить два числа, то мы должны в процессор поместить два этих числа в регистр. Специальное арифметико-логическое устройство, благодаря командам из которых состоит наша программа. Эти числа будут сложены, арифметико-логическое устройство выполнит операцию сложения и в итоге мы потом, уже результат выполнения арифметической операции, запишем в определенную ячейку памяти. В определенный байт. Но запомните, что вся информация кодируется в двоичном виде. Каждая лампочка может принимать состояние 1 или 0. 1 – горит ярко, 0 – горит в пол накала.
А теперь давайте рассмотрим какие же варианты хранения информации в ОЗУ у нас имеются. Может я хочу взять три байта. Могу ли я это сделать? Или два байта, или 5? Давайте посмотрим, что же допустимо. Обратите внимание, что мы можем одновременно воспользоваться либо одним байтом, либо двумя байтами. Та вот, два байта всегда сленгово называли машинным словом. То есть два байта – это 16 лампочек, 16 бит. Получается, что если у меня имеется число до 256 – я его могу закодировать одним байтом. Потому что мы с вами видели уже на слайдах с яблоками, что я могу закодировать любое число в одном байте от 0 до 255. Итого 256 комбинаций с 0. А если мне надо 1000? А если мне надо число 256? На единичку больше чем допустимый диапазон в одном байте. Тебе надо девятая лампочка. Но у нас физически нет таких ящиков, которые содержат в себе именно 9 байт. И поэтому мы добавляем еще один байт. И получается, что одновременно мы число можем закодировать либо одним байтом, либо двумя байтами, либо четырьмя байтами – двойное машинное слово. Либо восемью байтами. И получается, что 8 байт – 64 бита в этой последовательности. Запомните, варианты хранения информации в ОЗУ это либо 1 байт, мы можем обращаться к одному байту, либо к двум байтам, либо к четырем, либо к восьми и в зависимости от этого правила мы и будем строить наши сущности – переменные, к которым мы с вами подходим. Я пока не скажу, что такое переменная. Еще раз один байт, два байта, четыре, восемь.
А теперь, давайте мы подойдем к системам счисления. Посмотрим, как же все сказанное, а особенно тот пример с яблоками, должен быть представлен формально в виде цифр. Давайте мы перейдем к следующему слайду и посмотрим. У нас в мире существует две разновидности систем счисления. Это позиционная и непозиционная системы. Что это такое? Чем они отличаются. Дело в том, что для записи числа, любого числа, мы можем использовать, по сути, любые символы. Раньше, когда не было цифр, многие народности просто использовали символы из своих алфавитов. И важно понимать, что их символы символизировали не именно то, что символизируют сейчас цифры. Обратите внимание! Вот у нас идет греческий алфавит. Альфа, бета, гама, эпсилон, дельта, дзета, тэта, йота… Вот эти символы символизировали вот такие веса: 1, 2, 3, 4, 5, 6, 7, 8, 9. Обратите внимание! Например, лямбда – 30, мю – 40, икс – 600, омега – 800, 900. А понятия тысяча просто не было. То есть, не любое число можно было записать. Но позже появились позиционные системы. Позиционные были почти у всех народов. И ветхославянская система, и греческая система, только не путаем римскую, там смешенная система. Нас непозиционные системы даже не интересуют. Нас интересуют настоящие системы – это позиционные. А почему эта называется позиционной, а другая – непозиционной? Потому что, если бы мне нужно было закодировать число 33, я мог сначала поставить лямбду и гамму. Если я их переставлю местами, значение от этого абсолютно не поменяется. То есть вот так записывались числа и были так называемые нумерологи, которые брали какое-то число, меняли в нем буквы местами и говорили, что вот это вот слово «Иисус», а вот это вот слово «Дьявол». Вот это слово плохое, а вот это – хорошее, потому что одно символизирует одно понятие, либо другое понятие. Вот от таких игр с числами появились такие понятия, что число 666 – число дьявола, а 777 – Бога. Думаю, что кто-то верит в это, а кто-то нет. Дальше. А что же такое позиционная система счисления. Арабы сидели и считали, например, своих верблюдов и тюки с хлопком или еще с чем-то. Представьте себе, сидит Мухаммед бен Муса аль-Хорезми, пишет свой трактат Китаб аль-джабр ва-ль-мукабала и параллельно еще считает верблюдов. Смотрите, он взял положил три тряпочки и у него есть палочки. Синяя палочка весом в 1 грамм. Зеленая палочка весом в 10 грамм. Он считает: один верблюд, еще одна палочка, еще одна палочка, три, четыре, пять, шесть, семь, восемь, девять. Заметьте, как только он кладет последнюю палочку здесь оказывается 10 палочек, 10 грамм в разряде единиц. Что он делает? Он берет, выделяет все эти палочки, удаляет их отсюда, берет одну палочку в 10 грамм и кладет на соседнюю тряпочку, а на первую берет бублик и кладет бублик. У нас получилось число 10. Ноль единиц в разряде единиц и одна тяжелая единица в разряде десятков. И так пошло дальше. Если он туда кладет еще одну палочку, 0 убирается и у нас получается число 11. Если он кладет еще одну палочку, получается число 12 и при этом его позвали обедать. Поэтому, ему нужно срочно записать это число. И что он сделал? Он придумал всего лишь некие символы для каждой из цифр. Каждое количество палочек выражено одним символом. Поэтому для записи арабских чисел используются 10 чисел от 0 до 9. А теперь давайте посмотрим что было в Китае. Сидит китайская принцесса и считает гусениц тутового шелкопряда. Она считает вот так: раз гусеница, два гусеница, три гусеница, четыре гусеница, пять гусеница. Если арабы считали на двух руках, то китайцы считали на одной руке. Выделяет все эти палочки и удаляет их. Берет одну палочку весом в 10 грамм и кладет ее на вторую тряпочку, а на первую кладет нолик. У нее тоже получилась десятка, но ее десятка не весит 10 грамм а всего 5 грамм, но тем не менее, цифра получилась та. Если мы возьмем 10 китайскую и 10 арабскую, мы с виду их не отличим. Поэтому, когда встречаются китайская принцесса и Мухаммед бен Муса аль-Хорезми китайская принцесса говорит: «У меня есть 20 яблок». Мухаммед быстро перечитал и понял, что у нее только 10 яблок. И когда принцесса говорит, что у нее есть 10 гусениц тутового шелкопряда, и она хочет их поменять на какие-то арабские продукты. Мухаммед знает, что у нее не 10, а всего лишь пять гусениц. Все потому, что арабы считали на двух руках, а китайцы на одной. Но это всего лишь форма записи числа. Китайцам было удобней считать на одной руке, арабам было удобней считать на двух руках. Совсем недавно, в России, больше ста лет назад использовалась двенадцатеричная система счисления. А по чем считали в двенадцатеричной системе? На одной руке по фалангам пальцев. Двенадцатеричную систему мы с вами еще сегодня посмотрим. Главное запомните, что вся простейшая арифметика строится на первоклассных палочках. Если вы были первоклассник русской или арабской школы, то высчитали по 10 палочек. Если же вы китаец и учились в китайской школе, точнее в древнекитайской, потому что сейчас все приняли арабскую систему, то вы бы считали по 5 палочек. Но по весу эти числа отличаются. Десятка китайская весит 5 грамм, а десятка арабская – 10. Поэтому, когда мы работаем с разными системами счисления мы должны учитывать эти поправки чтобы не обмануться. А при чем же здесь программирование? Смотрите что сделали электронщики. Они сказали, что в машине тоже идут биты. Нулевой, первый, второй… И когда мы кладем в нулевой бит 1, а в других лежат 0. Что произойдет, если добавить еще одну единицу. Две палочки убираются, происходит перенос во второй разряд. И в нашем случае получается, что 1+1=10. Если у китайцев было 1+1=2, 2+1=3, 3+1=4, 4+1=10. У них нет числа 5, у них нет такой цифры. А арабов будет 4+1=5, 5+1=6, 6+1=7, 7+1=8, 8+1=9, 9+1=10. Основание любой системы счисления. И у каждой системы счисления есть свой вес, состояние. У электронщиков в вычислительной машине десятка весит два грамма, у китайцев – это 5 грамм, у арабов – 10. А шестнадцатеричная система? Мы ее рассмотрим немножко попозже. Главное, чтобы вы поняли, что машинная арифметика не сложнее той арифметики, которую проходили в садике до того как пойти в первый класс.
А мы с вами продолжаем. Переходим в нашу презентацию. У нас в мире есть две разновидности систем счисления. Это непозиционная и позиционная, а непозиционная более не используется. Переходим к следующему слайду и, как мы уже говорили, десятичная система счисления – это позиционная система счисления с основанием 10. Обратите внимание, как записывается число: разряд единиц, разряд десятков, разряд сотен, разряд сотен, разряд тысяч и т.д. И мы видим, что для записи числа у нас используются цифры от 0 до 9. Давайте дальше посмотрим. Вот у нас идут верблюды, которых считал Мухаммед, и вот шелковые платья, которые считала принцесса. И мы видим, что для записи числа китайцы использовали только 5 чисел – 01234. У них не было такого понятия как 5. У них не было такого символа.
Вот мы переходим к двенадцатеричной системе счисления. Это позиционная система счисления с основанием 12. Давайте посмотрим на часы. 123456789. Получается, что им нужно было придумать еще какие-то символы для записи в разряде единиц. Мы можем использовать буквы латинского алфавита – АВ. 9+1=А, А+1=В, В+1=10, 10+1=11. Эта система счисления уже не используется, но мы ее помним постоянно. Знаете несчастливое число – 13. А почему оно несчастливое? Все очень просто. До изменение системы счисления, считали, что число 11 несчастливое, потому что напоминает рога дьявола. И из квартир убирали 11, потому что они напоминали рога дьявола. Но когда перевели систему счисления с двенадцатеричной на десятичную, то число 11 стало числом 13 и ни в чем не повинное, не похожее на рога дьявола число 13 стало автоматически плохим. Если я смотрю с окна, то даже нет 13 номера автостоянки. Идет 11, 12, и 14. Лечу в аэробусе, сижу на 14 ряду, передо мной – 12. Люди боятся безобидного числа 13, которое вообще не символизирует рога дьявола. Для записи числа используются цифры от 0 до В. Приходится использовать еще и буквы, потому что мы кладем больше палочек, чем было у арабов, поэтому нужно выдумывать новые символы для записи того или иного числа. И мы видим, что число 10 в двенадцатеричной системе равно 12 в десятичной системе. 10 в двенадцатеричной всегда называлось дюжиной. Число 11 – чертовой дюжиной. Число 100 называлось гросс. Но это нам не интересно, это история. Зачем мы это рассматриваем? А затем, что мы с вами посмотрели относительно нашей привычной десятичной системы счисления с основанием в 10 грамм были системы, у которых основания 5 грамм у китайцев, или 2 грамма – у электронщиков. Но также были системы, у которых основание больше: это двенадцатеричная. Десятка весит 12 грамм. Есть еще одна интересная система счисления – шестнадцатеричная. В ней десятка весит 16 грамм. Мы с вами переходим к следующему слайду. Двоичная система. Десятка в двоичной системе весит 2 грамма. 10 в двоичной системе равно двум в десятичной. Каждая система, как двоичная, как пятеричная, как десятичная, они могут проецироваться одна на другую. Давайте посмотрим на эту маленькую табличку. Мы видим, что числа в десятичной системе идут 0, 1, 2, 3, 4, 5, 6, 7, 8, каждое следующее число – это предыдущее, увеличенное на единицу. А в двоичной 0, 1, 10, 11, 100, 101, 110, 111, 1000. Видим, что двоичная система проецируется на десятичную. Можно и на пятеричную спроецироваться. А мы идем дальше по презентации. Шестнадцатеричная система счисления. Ее цифры для записи числа: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, A, B, C, D, E, F. C весит 12 грамм или 1100 в двоичной. Интересно, что шестнадцатеричная система совпадает с двоичной, 0 совпадает с 0, а F совпадает с 1111. Обратите внимание, четыре бита. А четыре бита где помещаются? Они помещаются в полубайт. Младшая половина и старшая половина. Полубайт в информатике называется тетрада. Мы раньше работали с триадами. Байт был тоже восьмибитовый, но была другая система счисления. Мы не будем сейчас о ней говорить. Но раньше работали с восьмеричной системой. Шестнадцатеричная система была взята электронщиками только для удобного представления полубайта, потому что у нас в байте имеется два полубайта: младший и старший. И получается, что эти сложные и заковыристые значения соответствуют цифрам шестнадцатеричной системы. Теперь их легко выучить. Электронщики все знают шестнадцатеричную систему, вам тоже было бы полезно ее знать. Теперь мы можем полубайт представить в виде одного числа. Многие из вас пользовались такими программами как Total Commander, и если там нажать F3 на какой-то программе, то вы видели какие-то цифры A3 B4 FF 15. Сложно было, непонятно. Теперь мы понимаем, что стоящие рядом такие буквы и цифры обозначают значение одного байта. И мы с вами сейчас это посмотрим. И мы в редакторе HxD, который позволяет просматривать шестнадцатеричные коды, берем и открываем ConsoleApplication.exe из примеров предыдущего урока. Обратите внимание, что мы видим. Такие представления. Каждая пара символов – это один байт. Давайте попробуем расшифровать байт ВА. В = 1011. Расшифровали старший полубайт. А = 1010. Видите? Но для того, чтобы нам не писать такие длинные последовательности двоичных чисел электронщики взяли за основу шестнадцатеричную систему счисления для удобного представления для чтения человеком кодов программ. Чтобы люди могли хоть как-то ориентироваться в этих программах. Представьте, что здесь бы были одни единицы и нули. Мы бы сошли с ума. Если тут мы еще что-то можем понять. Вот вверху идет DOS заголовок, потому что вдруг мы нашу программу захотим запустить под DOS. Вот здесь идет DOS прерывание, потом данные. Вот идут команды ассемблера. Если вы его учили в институте, вы поймете. А если нет, то может еще будете изучать. Вот смотрите, здесь представлены машинные команды. А дальше представлены тексты. И все закодировано в шестнадцатеричной системе. Нет в двоичной, просто у нас имеется шестнадцатеричное представление, чтобы мы могли читать эти программы. И вы видите, каждый байт, он представлен в шестнадцатеричном формате.
Мы переходим дальше по презентации. Вы видите, что любое число, что мы с вами и видели в том текстовом редакторе, оно состоит из двух частей. Младшая тетрада и старшая тетрада. Тетрада – это полубайт. Младшая группа – 4 лампочки, старшая группа – 4 лампочки. И мы можем в удобной форме для человека представить их не в двоичных кодах, а в шестнадцатеричных. Поэтому двоичная система, она в электронике используется только для удобства чтения и анализа машинных кодов. Но машина не работает в шестнадцатеричной системе и нет такой смешанной двоично-шестнадцатеричной системы. Потому что мы понимаем, что шестнадцатеричная система здесь используется для удобно представления для чтения человеком двоично закодированного числа. И вот смотрим дальше. Здесь видим, как раз значение нашего байта. Давайте посмотрим что это за число. 1110 = Е. 1101 = D. Если у вас возникают трудности, то вы можете по вот этим таблицам находить, и у вас в примерах к уроку имеется полный файл с описанием вот как раз полностью всего диапазона чисел, которые могут входить в байт. И сейчас я посмотрю… Вот вы видите, что у нас имеется XPS файл, в котором вы можете посмотреть соответствия все 256 чисел. Руководствуясь этой табличкой, вы можете видеть код любого шестнадцатеричного числа, его эквивалент в десятичной системе. Здесь предоставлен весь диапазон байта, все те числа, которые мы можем закодировать одним байтом. Имеется возможность ручного перевода десятичного числа в двоичное. Здесь имеется его формула. Здесь польская запись числа. Мы не будем делать акцент на переводе числа. Здесь есть перевод десятичного числа в двоичное, двоичного в десятичное, перевод десятичного в шестнадцатеричное, шестнадцатеричного в десятичное. Но нам это не интересно, потому что у нас есть калькулятор. Обратите внимание! У нас имеется калькулятор. Выполним команду Win+R. Напишем calc. У нас появляется калькулятор обычный. Теперь смотрим View\Programmer. Обратите внимание. Вот он трансформировался. И теперь мы хотим узнать, вот тут выбрано Decimal, Hex – шестнадцатеричное, Decimal – десятичное, Oct – восьмеричное, это как раз та восьмеричная система, которая использовалась лет так 20 назад, потому что байт имел немножко другую структуру. Там не было две тетрады, там было две триады. Две группы по три и два отдельно стоящий бита, которые обозначали бит знака и бит четности. Но о знаковых числах мы поговорим немножко попозже. Вдруг нам придётся анализировать старую программу и переводить ее в новую, но я думаю, что вам такое не придётся делать я просто показываю, что здесь в калькуляторе. Bin – двоичные. Вот мы выбираем десятичное число, десятичную систему, и ввожу число 255, интересно чему оно равно. Выбираем Hex… FF. А если в двоичную – 11111111. Видите, полностью все лампочки загорелись. Хорошо, а если я хочу посмотреть число 256. Чему равно это число в двоичной? 100000000. Вы видите, единица выпрыгнула за диапазон байта. Почему? Потому что для хранения такого числа нам нужно два байта. Три байта вместе нельзя использовать. Можно использовать только либо 1, либо 2, либо 4, либо 8 байт. А теперь мы это двоичное число хотим представить в шестнадцатеричном… Это число 100. Калькулятор всегда вам может помочь в режиме Programmer, всегда он может перевести одно число в другое. Хорошо. На этом мы с вами закончили обзор систем счисления, разбор машинной арифметики. Вы видите, что эта арифметика очень простая. Возможно она вам немножко непривычна, но не спорьте, что это арифметика детского сада и первого класса. Вы даже не можете спорить с этим. Замечательно, что вы все поняли. И, я думаю, у вас все получится.
Сейчас переходим к рассмотрению языка C#. К рассмотрению его самых начальных конструкций – это переменные и типы данных, которые хранятся в этих переменных. И теперь – переменные. Обратите внимание! Снова знакомая планка ОЗУ. Смотрите, ящик с битами. Какие-то лампочки горят в пол накала и одна горит ярко. Быстренько их перекодируем. Пол накала – 0. Ярко – 1. Вот у нас байт хранит в себе некое значение. А число 10 это какое? 10 = 2. Как нам сделать так, чтобы в ОЗУ взять такой ящик и закодировать в нем число 2. На языке программирования мы должны написать такую конструкцию.
byte a = 2;
Мы создаем переменную типа byte. Мы так и пишем. Пишем «а», а перед ним пишем сколько, какой обьем информации в ОЗУ, сколько таких ящиков мы хотим выделить для записи нашего числа. Еще раз. Мы создаем переменную с именем «а». Что за «а»? Это же виртуальный мир. Мы используем обычные человеческие имена, например «а», или «name», или «operand1», или «digit». Для того чтобы нам не пользоваться этими сложными и длинными кодами. Поэтому мы их заменяем нормальными человеческими представлениями, но здесь мы поставили просто букву «а», как в математике. Что мы здесь делаем? Мы создаем переменную «а», типа byte, это значит, что мы просим, чтобы у нас в памяти выделился один байт. Дальше знак равно. Это не знак равенства как в математике. В информатике это знак присвоения, знак помещения в переменную «а» того, что находится справа от этого знака. Мы создаем переменную с именем «а» типа byte и присваиваем ей значение 2. Конечно же здесь мы используем значение в десятичной системе, но мы понимаем, что оно в итоге перекодируется в двоичное представление. Давайте посмотрим сейчас определение понятия переменной. Переменная – это область памяти, которая хранит в себе некоторые значения, которое можно изменить. Мы здесь только создаем переменную и присваиваем ей некоторое значение. Давайте мы сейчас зайдем в Visual Studio. У вас к данному уроку идет папка с примерами. Вы ее можете открыть, и мы заходим в первый проект.
Обратите внимание, что у нас здесь происходит! Мы с вами условились что пока не будем выходить за пределы операторных скобок метода Main. Этот Main мы запомнили, потому что он будет встречаться в каждой программе. Это есть точка входа, то есть то место, откуда он будет читать нашу программу.
1: using System; 2: 3: // Переменная (Variable) - это область памяти, которая хранит в себе некоторое значение, которое можно изменить. 4: 5: namespace TypeBasics 6: { 7: class Program 8: { 9: static void Main() 10: { 11: // На 13-й строке, создаем переменную с именем a, типа byte и присваиваем ей значение 2. 12: 13: byte a = 2; 14: 15: // На 17-й строке, выводим значение переменной - a, на экран. 16: 17: Console.WriteLine(a); 18: 19: // Задержка. 20: Console.ReadKey(); 21: } 22: } 23: }
Теперь смотрим на 13 строке мы создаем переменную с именем «а» типа byte и присваиваем ей значение 2. Мы берем, тем самым, выделяем в ОЗУ один байт. Мы просим машину выделить нам один байт и записываем в нее значение 2. На 17 строке мы выводим значение переменной «а» на экран. На 17 строке мы обращаемся к консоли. Помните, что такое консоль? Это экран и клавиатура. На 17 строке мы выводим на экран значение переменной «а» на экран. Давайте вернемся в нашу презентацию. Переходи к следующему слайду. Еще раз разберем момент создания переменной, который мы посмотрели в коде. Для того, чтобы создать переменную, мы должны указать тип переменной. Как мы уже понимаем, byte является типом. Мы можем в памяти выделить один байт, 2 байта, 4 или 8 байт. Давайте посмотрим еще раз на варианты хранения информации в ОЗУ. Если мы хотим выделить один байт, мы используем тип byte. Мы еще разберем, что такое sbyte и bool. Этих типов очень мало. Если мы хотим выделить два байта, например, для большого числа, мы будем использовать один из типов short, ushort. Если хотим выделить еще больше места, то нужно использовать типы int, uint. Если еще больше – long, ulong. Не переживайте, это только кажется сложным. На самом деле этих типов очень мало. Вот это основные базовые типы для выделения памяти. Возвращаемся в наш пример и еще раз смотрим. На 13 строке мы создаем переменную с именем а типа byte и присваиваем ей значение 2. То есть вы уже понимаете, что в памяти выделилось один байт. Возвращаемся в презентацию. Значит для того, чтобы нам создать в коде переменную. Мы должны указать тип, который говорит сколько байт в памяти будет занято под хранение того или иного значения. В данном случае сколько? Один! Далее мы указываем имя переменной. Что собой заменяет имя? Имя заменяет вот этот сложный адрес. Чтобы нам не помнить эти адреса, пусть их помнит кто? Visual Studio компилятор и все остальные, но не мы. Мы не хотим запоминать эти адреса. Представьте, что группа адресов хранит имя, а вот эта – цену, а вот эта – количество товара. Это невозможно запомнить все. И поэтому мы создаем такие аналоги, которые и ассоциируются с выделяемой памятью. Знак присвоения. Это значит, что мы берем и в переменную а, которая стоит слева от знака присвоения, помещаем то значение, которое стоит справа. «а» - имя переменной или идентификатор. byte – тип переменной. Он говорит сколько байт в данном случае выделит. И значение 2, это то значение, которое попадет в эту переменную. А как выделить два байта? Давайте посмотрим. Следующий слайд. Для этого нам нужно использовать другой тип. Мы создаем переменную с именем а типа short и присваиваем ей значение 256. Мы уже помним наш калькулятор. 256 – это 0х100 в шестнадцатеричной системе. Шестнадцатеричное число в шестнадцатеричной системе записывается так: 0х100, чтобы мы могли отличить его от десятичного числа. А число в двоичной системе имеет вот такое окончание – b. Шестнадцатеричная – Hex, двоичная – binary. И мы видим, что число 256 в двоичной системе можно представить, как 0000 0001 0000 0000 b, что соответственно представлено в шестнадцатеричной так 0х100. Мы взяли и выделили два байта. Но это здесь на этом слайде они сначала, возможно это будут какие-то в середине два байта. Это как решит загрузчик операционной системы. Мы не знаем, как это будет. Это мы здесь для примера показываем, что выделено два байта именно в начале. Мы создаем переменную с именем а типа short, это значит, что мы просим два байта в памяти и записываем в выделенную область значение 256 в двоичном виде.
Переходим дальше и еще раз смотрим на типы данных. Мы можем использовать либо 1 байт, 2, 4, либо 8 байт. Посмотрите на следующий слайд. Здесь показаны все основные предопределенные типы данных, которые используются в языке C#. Смотрите как их мало. Какие мы уже здесь знаем? Со строкой уже работали, еще видели byte, и short. Мы видим, что byte восьмибитовый и short 16-битовый. Оказывается, у нас есть числовые типы, которые разделяются на целочисленные, десятичные и вещественные, числа с плавающей точкой. Если вы с института помните вещественную арифметику. У нас есть нечисловые типы. Булевы и символьные. Нечисловые и Числовые – это простые. Есть не совсем простые. Object – это главный тип, мы с ним будем знакомится на следующем курсе, string – здесь познакомимся, dynamic – динамический тип, с которым будем знакомится на C# Essential. Обратите внимание. Самые простейшие типы данных. Мы с ними всеми с вами познакомимся за сегодня и за завтра. Ну практически со всеми.
Ну а мы переходим в Visual Studio и движемся по практической составляющей наших уроков, нашего этого урока, потому что в дальнейшем у нас не будет таких больших презентаций, таких длинный изложений. Мы будем больше работать с программными кодами, анализировать коды программ смотреть как работает та или иная программа. Потому что первые два урока конечно, первый урок, помните, вчерашний – это было введение в C#. Мы посмотрели возможности этого языка. А сегодня мы посмотрели очень важный раздел машинной математики, который позволит нам четко и ясно понимать, как же эти переменные хранятся в памяти. У нас теперь это не будет черный ящик, какая-то коробочка, в которой хранятся яблоки. Нет, мы уже смотрим профессионально как переменные хранятся в ОЗУ, для хранения значения этих переменных выделяется какое-то пространство в этой памяти. Либо 1, 2, 4, 8 байт. Мы теперь понимаем это в правильном контексте. А мы с вами перейдем к следующему примеру.
Давайте зайдем во второй проект Alias
1: using System; 2: 3: namespace Alias 4: { 5: class Program 6: { 7: static void Main() 8: { 9: // Тип данных C# (псевдоним) 10: byte a = 2; 11: 12: // Системный тип данных 13: Byte b = 2; 14: 15: // Вывод значений переменных на экран. 16: Console.WriteLine(a); 17: Console.WriteLine(b); 18: 19: // Задержка. 20: Console.ReadKey(); 21: } 22: } 23: }
На 10 стоке мы создаем переменную с именем а типа byte и присваиваем ей значение 2. Обратите внимание! На 13 строке мы создаем переменную b типа Byte и присваиваем значение 2. Обратите внимание. Здесь вот таким синим, а здесь бирюзовым. Интересно, чем же это отличается. А дело в том, что настоящий тип, это Byte. А вот этот тип byte – это его alias. Мы пока не будем разбирать. Alias – это псевдоним. Мое полное имя – Александр, а это мой псевдоним, кличка – Саша. Зачем так сделали? Во первых, для удобства, потому что многие программисты переходят на C# с других языков с си подобным синтаксисом, потому что как Java, как C#, как С++. Они все используют диалект языка С. Нельзя сказать, что Java похож на С++ или Java похож на C#, или C# на Java. Это не правильно. Они все похожи, они все используют один диалект языка С. Они все используют структурную нотацию языка С. Для того, чтобы нам выделить байт в памяти нам нужно использовать либо ключевое слово byte либо Byte. Мы дальше еще будем смотреть на эти alias. И дальше на 16-17 строках мы выводи на экран значение переменный а и b. На 20 строке ожидаем ввода пользователя для программа не закрылась после завершения работы. Выполнимся. Давайте посмотрим что мы видим в результате выполнения этой программы. Обратите внимание! Вот, 16 строка у нас выводит первую двойку. 17 строка выводит вторую двойку. А что будет, если мы изменим значение переменной b. Давайте посмотрим. Измените у себя тоже. Выполняемся… b у нас чему уже равна – 4. Вы видите? Вывелась 4. Этот пример показал, что у многих базовых типов имеются alias. Но, здесь есть еще одна беда. На самом деле, язык C# является полностью объектно-ориентированным языком. Если мы зайдем и посмотрим внутрь переменной byte. Давайте зайдем посмотрим, вдруг вот этот byte не такой как этот Byte. Нажмем F12. Мы заходим и видим что это все-таки не один байт. Это сложная структура данных. Почему Microsoft так сделали? Почему теперь мы используем не просто один байт, а еще кучу вспомогательной функциональности. Вы видите? В один байт все это не поместится. Это сделано для удобства и безопасности. А представьте себе, человека без одежды, в чем мать родила. Вы представляете себе? Зимой на улицу взять и выставить такого человека. Что с ним произойдет? Он будет мерзнуть. А мы ему с окна говорим: «А может ботинки, куртку, штаны, машину, квартиру, денег?» Он будет соглашаться. Вы же не отказываетесь от всего этого богатства, хотя человек может жить без ничего. Но мы же так не делаем, мы постоянно обрастаем какой-то полезной функциональностью. Потому что нам удобно так жить. Мы не мерзнем, мы не болеем, мы не колем ноги. Вы видите, мы можем купить что-то. Мы можем красиво выглядеть. Так же и здесь Microsoft берет и отказывается от подхода чистого байта. Вот этот байт содержит в себе множество вспомогательной функциональности, которая помогает программистам общаться с этим байтом более безопасно. Но об этом мы с вами будем говорить, потому что такое объяснение вульгарно-прямолинейное объяснение, но на данном этапе я думаю, что его будет достаточно. Смотрим, у нас есть у простых типов данных как их псевдонимы, и на 13 строке мы видим настоящий тип данных, то есть настоящее полное имя. Но вы должно понимать, что это один и тот же тип, который используется с разными переменными а и b.
Переходи к следующему примеру
1: using System; 2: 3: namespace BasicTypes 4: { 5: class Program 6: { 7: static void Main() 8: { 9: #region ЦЕЛЫЕ ТИПЫ 10: 11: // 8-bits == 1 byte. ---------------------------------------------------------------------------- 12: 13: // Целое без знака. Диапазон - от 0 до 255. 14: byte a = 0; 15: Byte b = 255; 16: 17: // Целое со знаком. Диапазон - от -128 до +127. 18: sbyte c = -128; 19: SByte d = +127; 20: 21: 22: // 16-bits == 2 bytes. ------------------------------------------------------------------------- 23: 24: // Целое без знака. Диапазон - от 0 до 65535. 25: ushort e = 0; 26: UInt16 f = 65535; 27: 28: // Целое со знаком. Диапазон - от -32768 до +32767. 29: short g = -32768; 30: Int16 h = +32767; 31: 32: 33: // 32-bits = 4 bytes. --------------------------------------------------------------------------- 34: 35: // Целое без знака. Диапазон - от 0 до 4294967295. 36: uint i = 0u; 37: UInt32 j = 4294967295U; 38: 39: // Целое со знаком. Диапазон - от -2147483648 до +2147483647. 40: int k = -2147483648; 41: Int32 l = +2147483647; 42: 43: 44: // 64-bits = 8 bytes. --------------------------------------------------------------------------- 45: 46: // Целое без знака. Диапазон - от 0 до 18446744073709551615. 47: ulong m = 0ul; 48: UInt64 n = 18446744073709551615UL; 49: 50: // Целое со знаком. Диапазон - от -9223372036854775808 до +9223372036854775807. 51: long o = -9223372036854775808L; 52: Int64 p = +9223372036854775807L; 53: 54: #endregion 55: 56: 57: #region ВЕЩЕСТВЕННЫЕ ТИПЫ 58: 59: // Вещественные типы предназначены для представления дробных чисел. 60: 61: // 32-bits = 4 bytes. --------------------------------------------------------------------------- 62: 63: // Вещественное со знаком. Диапазон - от +/-1.5 x 10^-45 до +/-3.4 x 10^38. 64: float q = -0.123456789f; // Указание суффикса f, является обязательным, 65: Single r = +1.123456789F; // т.к., компилятор интерпретирует данное число как double. 66: 67: 68: // 64-bits = 8 bytes. --------------------------------------------------------------------------- 69: 70: // Вещественное со знаком. Диапазон - от +/-5.0 x 10^-324 до +/-1.7 x 10^308. 71: double s = -0.123456789d; 72: Double t = +1.123456789; 73: 74: #endregion 75: 76: 77: #region ДЕСЯТИЧНЫЙ ТИП 78: 79: // 128-bits = 16 bytes. ----------------------------------------------------------------------- 80: 81: // Десятичное со знаком. Диапазон - от от +/-1.0 x 10^-28 до +/-7.9 x 10^28. 82: decimal u = -0.12345m; // Указание суффикса m, является обязательным, 83: Decimal v = +1.1234567M; // т.к., компилятор интерпретирует данное число как double. 84: 85: #endregion 86: 87: 88: #region ЛОГИЧЕСКИЙ ТИП 89: 90: // 8-bits == 1 byte. ---------------------------------------------------------------------------- 91: 92: // Логическая величина Истина/Ложь. 93: bool w = true; 94: Boolean x = false; 95: 96: #endregion 97: 98: 99: #region СИМВОЛЬНЫЙ ТИП 100: 101: // 16-bits == 2 bytes. ------------------------------------------------------------------------- 102: 103: // Символ в формате UNICODE. 104: char y = 'a'; 105: Char z = 'A'; 106: 107: #endregion 108: 109: 110: #region СТРОКОВОЙ ТИП 111: 112: // Строка в формате UNICODE. 113: string firstString = "hello"; 114: String secondString = "HELLO"; 115: 116: #endregion 117: 118: 119: // Задержка. 120: Console.ReadKey(); 121: } 122: } 123: }
И мы видим на 9 строке какой-то прямоугольник и написано «целые типы». А давайте теперь нажмем плюсик возле него. У нас разварачивается этот прямоугольник. Смотрите как удобно! Смотрите, а зачем же нужны такие участки? Смотрите, это директива препроцессора. Препроцессор – это тот механизм, который обслуживает нас сейчас в сеансе пользования Visual Studio. Уже мы видим, что препроцессор позволяет нам сворачивать и разворачивать лишние коды. А программы иногда состоят их сотен, а иногда тысяч строк кода. Иногда в одном файле бывает несколько сотен строк кода. И поэтому нам удобно сворачивать и разворачивать эти участки. Это никак не влияет на процесс выполнения программы, это просто удобство для программиста. И в этом примере мы должны рассмотреть все типы данных, все простейшие типы данных. Целые типы. Вещественные типы. Десятичные типы. Логический тип. Символьный тип. И строковой тип. И мы сейчас с вами их рассмотрим. Целые типы у нас бывают восьмибитовые, то есть однобайтовые. Это целые бес знака. Что значит бес знака? У нас имеется две разновидности чисел – это натуральные числа, для подсчетов предметов и различные иррациональные, рациональные числа, которые могут быть как положительными, так и отрицательными. Но натуральное число не быть ни положительным, ни отрицательным. Оно может быть просто число. Я не смогу сказать, что у меня -2 яблока, я не могу сказать, что у меня -3 компьютера. И поэтому для натуральный чисел используется вот такие типы данных как byte. Мы сюда не можем записать число -255. Значит целое без знаковое. Но если вы скажете, что хотите со знаком число, чтобы температуру представить, например. Мы берем и используем тип sbyte. На 14 строке мы создаем переменную а типа byte и присваиваем ей значение 0. На 15 строке мы создаем переменную с именем b типа byte и присваиваем ей значение 255. Мы видим, что первый байт – это alias, второй Byte – полное имя. На 18 строке мы создаем переменную с именем с типа sbyte – signed byte – знаковый байт. Значит мы здесь храним либо положительное, либо отрицательное число. У них есть свой диапазон. Если у без знакового есть от 0 до 255, то это число от -128 до 127. Почему так? Пока просто запомните, потому что машинная математика именно со знаковыми числами будет нами разобрана немножко попозже. Сейчас просто получайте удовольствие и понимайте, что такой тип данных содержит такие значения, а такой другие. 22 строка – 16 битовые. То есть, для того что бы в памяти выделить два байта нам нужно использовать типы либо ushort, либо short. Ushort – unsigned short. Без знаковое короткое число. Двухбайтовое. Его настоящее название UInt16. 16 говорит о том, что число имеет 16 бит. Теперь смотрим знаковые числа. Short. Мы выделяем два байта, но при этом мы в такую переменную можем записывать либо только отрицательные, либо только положительные числа, и заметьте, вот этот знак плюс указывать здесь необязательно. Если ushort – это псевдоним, то UInt16 – это полное имя. Если мы хотим выделит 4 байта. На 36 строке создаем переменную с именем i типа uint. U – unsigned – не знаковое int, integer. И присваиваем значение 0. U – это не обязательный суффикс, который говорит, что это uint, потому что если это число будет использоваться где-то отдельно без переменной то я смогу увидеть какое число здесь присваивается. И эти суффиксы мы разберем с вами подробней далее. Они у нас будут встречаться. Uint – это alias, а UInt32 – это полное имя. Запомните Саша – Александр, Ваня – Иван, Вася – Василий, Маша – Мария. На 40 строке мы создаем переменную k типа int – это знаковое. Мы сюда записываем либо отрицательные, либо положительные числа. Мы видим на 40 и 41 строке. 40 – alias, 41 – полное имя. Смотрим дальше, 8 байтовые. На 47 строке мы создаем переменную с именем m типа ulong – unsigned long и присваиваем значение 0. Смотрите, суффикс ul. Это вспомогательный суффикс, его можно не указывать. И настоящее имя – UInt64. 51 строка – мы создаем переменную о типа long и присваиваем ей некоторое значение. Обратите внимание, long – знаковое. Это нужно запомнить. Вам важно понимать, что программирование, это не только понимание, это еще немножко запоминание. Это же язык, пусть это маленький язык. Вы можете просто изучая английский язык, его просто понять, но не запоминать слова? Нет, это невозможно. Вы можете изучать математику, или какую-то науку и просто понять и больше ничего не учить? Такого не бывает. Так почему же некоторые программисты хотят только выучить и ничего не запоминать. Вы никогда не станете профессиональным программистом и профессионалом в своей области, если не будете чего-то учить. Поэтому, хотя бы немного, но мы будем учить. Хорошо, мы посмотрели, у нас имеются целые типы. Сколько их? Два однобайтовых, два двухбайтовых, два четырехбайтовых, два восьмибайтовых. Всего 8. Следующий тип – это вещественные типы. Их мало, их только два. В компьютере на самом деле два процессора. Один называется CPU – Central Processor Unit. А в нем встроен FPU – Float Point Unit. То есть процессор для работы с числами с плавающей точкой. Мы не будем говорить о сложностях этого числа, просто представьте, что это дробное число. Этот процессор, это вещественное устройство, которое может работать с двумя типами данных, но на самом деле он поддерживает три типа данных. У него еще есть один 24 битовый формат, но он настолько меленький, что разработчики языка C# решили его просто не включать. И поэтому в FPU или сопроцессоре имеется три типа данных с которыми он может работать. Это 24 битовые, 32 битовые и 64 битовые. Но 24 битовое число оно такое маленькое, что характеристика числа занимает много, а под мантиссу числа остается совсем мало, мы им можем просто пренебречь. Поэтому в языке C# остается только 2 вещественных типа. Это float – псевдоним, Single – настоящее имя. Почему он называется Single? А потому что у вещественных чисел есть понятие точности числа а точность числа определяется количеством знаков после запятой. Какое число точнее? 3,1 или 3,14. Второе число представлено с двойной точностью 71 строка – это double. Как псевдоним double, так и полное имя Double. Мы видим, что в C# мы можем работать только с двумя типами вещественных чисел. Почему говорится Single? Single precision – одинарная точность. И в вещественной математике у нас идут такие числа – digit with float point with single precision. Есть две разновидности вещественных чисел. Вы не можете здесь с целыми типами работать с целыми числами. Там просто произойдет обрезание дробной части числа. То есть потеря точности. Мы будем еще это с вами обсуждать. Какие у нас еще есть форматы? Восемь целых, два вещественных. Десятичный тип. Зачем же его придумали? Если у нас есть куча целых типов, куча вещественных типов. И тем более смотрите – десятичный тип работает с дробными числами. Очень просто. Расскажу такую историю. Не знаю, правда или не правда. Давным-давно, когда не было десятичных типов, были только два вещественных типа. А в вещественных типах у нас производится округление числа. Какие у нас бывают округления? С избытком и с недостатком. Вот девятку вы к чему округлите? Конечно же к 10, а вот эту восьмерку сделаю девяткой, а здесь поставлю ноль. А четверку к чему? Ближе к нулю. Так вот, представьте, что вы программист в банке где происходят транзакции с копейками и с десятыми копеек и в итоге получается, что у одних программистов больше округлений было с избытком, и получалось, что денег больше было. А другие честно выполняли арифметические операции, но у них были постоянные недостачи. Это что такое? Это проблемы с законом. И при чем не по вине программистов. И когда это поняли, электронщики решили исправить свою ошибку. Мы сделаем тип для финансовых расчетов и назвали его decimal. Давайте посмотрим дальше. Диапазоны всех типов, вы видели, в комментариях здесь отмечены. Логический тип данных. Вспомните классическую пропозициональную логику. Работа с высказываниями. Помните Аристотеля и его силлогизмы. Когда я сегодня шел на работу, я по дороге встретил большого розового динозавра. Это ложное высказывание, не может быть такого. Когда я сегодня шел на роботу, мне на встречу ехал белый мерседес. Это может быть правдой. Значит, первое высказывание – ложное, false. А второе высказывание было истинное. Так вот, пропозициональная логика работает с высказываниями. Классическая логика. И результатом высказывания может быть либо ложь, либо истина. И вот у нас есть специальных тип переменных, которые могут хранить результаты таких высказываний. Либо true, либо false. Обратите внимание! Названо тип bool. Не arist а bool, придумал то Аристотель, а Буль сформировал алгебру логики и у него нет таких понятий, как true и false. Потому что он заменил их на 1 и 0. Во многих языках программирования, таких как JavaScript или С++ нет разницы между true и 1. Мы можем в определенных конструкциях их подменять. В C# нельзя такого делать. Я бы назвал на месте Андерса Хейлсберга его, например, arist, но назвали bool. Ближе по эпохе. Следующий. Символьный тип. Мы знаем, что у нас может быть один символ. У нас есть кодовая таблица и эти кодовые таблицы символов они содержат набор всех символов, которые у нас встречаются и у каждого символа есть своя кодировка. Так вот, переменная типа char – character – символ. Мы создаем переменную y типа char и присваиваем ей один символ а. Эти символы хранятся в формате Юникод. А Юникод – это двухбайтовый формат. Под кодировку одного символа в памяти уходит два байта. Есть конечно более короткие форматы: ASCII, ANSI. По умолчанию Windows использует свою кодировку Юникод. Двумя байтами можно закодировать 65536. Замечательно. Смотрим дальше. Строковой тип. У нас есть еще один строковой тип. Смотрите, на 113 строке мы создаем переменную с именем firstString типа string и присваиваем ей значение Hello. Обратите внимание на 114 строке мы используем полноценное имя. Если на 113 мы используем alias – псевдоним. То на 114 мы используем полноценное имя. И присваиваем этой переменной строку. Строки хранятся тоже в формате Юникод. Давайте посмотри еще раз, какие есть типы. Целые типы, вещественные, десятичный, логический, символьный, строковый. Давайте зайдем еще раз в презентацию и посмотрим по нашему дереву какие мы здесь видели. Bool видели, char видели, decimal видели, float и double, sbyte, byte, short, ushort, int, uint, long, ulong. Еще мы видели string. Не видели только двух типов – это object и dynamic. C ними мы познакомимся позже, потому что они немножко необычны и немножко сложнее, чем вот эти простые типы. А мы с вами переходим дальше. Смотрите, мы здесь рассматриваем значения по умолчанию.
1: using System; 2: 3: namespace DefaultValues 4: { 5: class Program 6: { 7: static void Main() 8: { 9: // На 11-й строке, создаем переменную с именем a, типа byte и не присваиваем ей никакого значения. 10: 11: byte a; 12: bool b; 13: char c; 14: string s; 15: 16: // На 18-й строке - ОШИБКА: Запрещается использование неинициализированной локальной переменной! 17: 18: //Console.WriteLine(a); 19: 20: // Задержка. 21: Console.ReadKey(); 22: } 23: } 24: }
А что произойдет, если мы создадим переменную а ей ничего не присвоим. И какие вообще значения по умолчанию хранятся в переменных. На 11 строке мы создаем переменную a типа byte и ничего ей не присваиваем а на 18 строке мы можем попробовать вывести ее значение. Смотрите, подчеркивает красным. Вы пытаетесь использовать неинициализированную переменную. Что такое инициализация? Инициализация – это первое присвоение. Так всегда называлось, кода мы создаем переменную и присваиваем ей первый раз при создании какое-то значение – это называется инициализацией. Рождается человек и ему первый раз дают имя. Например, я родился, мне дали имя Александр. Меня инициализировали таким значением. Несколько дней я был вообще неинициализирован. Дальше я вырос и захотел поменять себе имя на Иван. Что я делаю? Я переприсваиваю себе имя. Но первое присвоение имени, значения переменной, это и есть инициализация. Нельзя говорить, что мы повторно инициализируем. Инициализация – это первое присвоение. Мы видим, что консоль не хочет работать с неинициализированной переменной. Поэтому если вы создаете переменные, то нужно их инициализировать. Дело в том, что ошибки выполнения не будет до тех пор, пока вы не попробуете использовать эту переменную. Использовать ее на чтение. Теперь смотрите, внизу я переменной а присваиваю значение 2. Теперь ошибка пропадает. Теперь консоль понимает, что эта переменная содержит значение. До этого она была непроинициализированна. Давайте посмотри следующий пример. Float, double и decimal. Мы с вами создаем три переменные. Одну float, одну double, одну decimal.
1: using System; 2: 3: // Выбор между типами float, double, decimal 4: 5: namespace FloatDoubleDecimal 6: { 7: class Program 8: { 9: static void Main() 10: { 11: float variable1 = 0.12345678901234567890f; 12: double variable2 = 0.12345678901234567890d; 13: decimal variable3 = 0.12345678901234567890m; 14: 15: Console.WriteLine(variable1); 16: 17: Console.WriteLine(variable2); 18: 19: Console.WriteLine(variable3); 20: 21: Console.ReadKey(); 22: } 23: } 24: }
Давайте выполнимся. Обратите внимание, мы вписали сюда длинные числа. Что произошло с числом float? Число обрезалось. Почему? Потому что оно короткое. Это короткий формат, в него не поместится большое число, не смотря на то что мы попытались в него записать длинное число. И смотрите, вы неявно его потеряли. Смотрим double. И в double потерялось. А вот decimal – это число еще больше. Это искусственное число, мы видим, что число типа decimal может хранить намного больше знаков после запятой. Для того, чтобы посмотреть максимально допустимые диапазоны чисел, вы можете кликнуть по float и нажать F12. Смотрим MaxValue и MinValue. Здесь числа представлены в экспоненциальном представлении. Смотрим теперь дальше. Ого здесь еще больше числа. Всего этого не пугайтесь, все это мы выучим. Это все проще чем переменные. Заходим в decimal. Ого какие числа здесь хранятся! По поводу размеров, вы можете ориентироваться на те значения, которые записаны в MaxValue и MinValue. И давайте зайдем в последний пример. Мы здесь имеем работу с символами.
1: using System; 2: 3: namespace Char 4: { 5: class Program 6: { 7: static void Main() 8: { 9: char a = 'A'; // Символ 10: char b = '\x0041'; // Значение в 16-ричном формате 11: char c = '\u0041'; // Значение в формате unicode 12: 13: Console.WriteLine(a); 14: Console.WriteLine(b); 15: Console.WriteLine(c); 16: 17: Console.ReadKey(); 18: } 19: } 20: }
На 9 строке мы создаем переменную а типа char – это двухбайтовая переменная. Теперь давайте выполнимся и посмотрим. Мы создали три переменные и создали в них значения. Первое значение в 16-ричном а на 11 строке – в формате Юникод. Это код большой буквы А в кодовой таблице. А какой код буквы B? Наверное 42. Выполняемся. Смотрите, большая В! Код 42, видите, мы поменяли. А какая маленькая буква а. Давайте проверим 61. И в кодовой таблице код символа а – это 61. А почему так? Очень просто. Если мы увеличим экран, смотрите что мы с вами видим. Каждый символ состоит из таких точечек – это знакоместо, в котором нарисована точечками картинка. 0041 – это всего лишь код этой картинки. Который будет выводится сюда. Это важно помнить. Поэтому мы видим, что мы можем символ представить просто символом, можем просто в 16-ричном значении, можем представить его в формате Юникод. Если вы поищите, то найдете очень много кодовых таблиц. Много было создано этих стандартов, я не буду сейчас о них говорить. Вот когда-то это было проблематично для программистов работать с подменой кодовых страниц, когда нужно было подставлять часть кириллицы для того, чтобы проводить русификацию программ. Сегодня Microsoft разработал двухбайтовый формат, который называется Юникод. 65536 различных символов. Это практически все символы, которые входят в алфавиты и даже куча там всяких кракозябликов, домиков и много чего. Вы можете видеть это. Хорошо. На этом мы закончим наш сегодняшний урок. Спасибо вам за внимание. Хочу заметить. У нас имеется ресурс testprovider.com. Пожалуйста, заходите, регистрируйтесь, проходите тесты после каждого урока, выполняйте рекомендации, которые даны в файлах, выполняйте домашние задания. Это практическая составляющая наших уроков. Вам это поможет. Еще раз спасибо за внимание. До новых встреч.