Автор Анна Евкова
Преподаватель который помогает студентам и школьникам в учёбе.

Понятие переменной в программировании. Виды и типы переменных (Оператор присваивания. Арифметические выражения)

Содержание:

ВВЕДЕНИЕ

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

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

Область видимости и/или время существования переменной в некоторых языках задаётся классом памяти.

Многие из нас слышали слово «переменная» на уроках математики задолго до того, как узнали многое о компьютерном программировании. Математическая переменная – это величина, значение которой неизвестно или не ограничено одним числом. Это использование похоже, хотя и не идентично, понятию переменной в языках программирования. Два важных различия:

Во-первых, в математике для представления переменной мы обычно используем букву, такую как x или y, тогда как в языках программирования мы часто используем описательное слово или фразу, такую как temperature, MaxValue или Number_of_Samples.

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

Глава 1. Понятие переменной. Типы.

Данные, как вы знаете, хранятся в памяти компьютера, но для указания на конкретную информацию очень неудобно все время записывать физические адреса ячеек. Эта проблема в языках программирования высокого уровня, в частности в Паскале, решена введением понятия переменной. Переменная в Паскале - именованный участок памяти для хранения данных определенного типа. Значение переменной (информация в соответствующих ячейках памяти) в ходе выполнения программы может быть изменено. Константами же, как вы уже знаете, называются величины, значение которых в ходе выполнения программы изменено быть не может. Конкретные переменные и константы представляют собой объекты уникальные и отличаются друг от друга именем.
В качестве данных в программах на языке Паскаль могут выступать числа, символы, целые строки символов. Заметьте, что с этими различными видами информации выполняются совершенно разные действия. Например, с числовыми величинами производятся арифметические операции, чего невозможно сделать с символьными. Кроме того, разные виды данных требуют различного объема памяти для хранения. В соответствии с этими соображениями в языке Паскаль введено понятие "Тип" (TYPE). Тип переменной указывает на то, какие данные могут быть сохранены в этом участке памяти, и в каких действиях эта переменная может участвовать. Существуют зарезервированные (базовые) типы в языке Паскаль, но, как далее вы убедитесь, есть также возможность создавать свои собственные, определяемые программистом типы переменных.
К базовым типам относятся:

  • целые чисел – «Integer»
  • тип "длинных" целых чисел – «Longint»
  • тип действительных (вещественных) чисел – «Real»
  • тип неотрицательных целых чисел от 0 до 255 – «Byte»
  • тип неотрицательных целых чисел от 0 до 65535 – «Word»
  • символьный тип – «Char»
  • строковый тип – «String»
  • логический тип – «Boolean»

Физически типы данных отличаются друг от друга количеством ячеек памяти (байтов), отводимых для хранения соответствующей переменной. Логическое же отличие проявляется в интерпретации хранящейся информации. Например, переменные типа Char и типа Byte занимают в памяти по одному байту. Однако в первом случае содержимое ячейки памяти интерпретируется как целое беззнаковое число, а во втором - как код (ASC) символа.
В отличие от констант, неименованных переменных не существует. Все используемые в программе переменные должны быть описаны в соответствующем разделе описания.

Раздел описания переменных начинается служебным словом Var, после которого следуют записи следующего вида:
<Список имен переменных>:<Название типа>;
Список может состоять из нескольких имен (при этом они разделяются запятыми), а также и из одного имени. Тип, указываемый после двоеточия, определяет, какие данные теперь могут храниться в описанных таким образом переменных. Для каждого используемого в программе типа переменных в разделе их описания должна быть, как минимум, одна собственная строка.
Пример:
Var
A,B,H_22,Angle : Real;
Name3 : String;
Flag : Boolean;
I,J,K,Count : Word;

1.1 Оператор присваивания. Арифметические выражения

Самым простым действием над переменной является занесение в нее величины соответствующего типа. Иногда говорят об этом, как о присвоении переменной конкретного значения. Такая команда (оператор) в общем виде выглядит на языке Паскаль следующим образом:
<Имя переменной>:=<Выражение>;
Выражение, указанное справа от знака ":=", должно приводить к значению того же типа, какого и сама переменная, или типа, совместимого с переменной относительно команды присваивания. Например, переменной типа Real можно присвоить значение типа Integer или Word (впрочем, наоборот делать нельзя). Выражение будет сначала вычислено, затем, его результат будет положен в ячейки памяти, отведенные для переменной.

Что же представляет собой выражение на языке Паскаль? Многое зависит от типа выражения. Рассмотрим сначала выражения арифметические, то есть те, результатом которых является число.
В состав арифметического выражения на языке Паскаль могут входить:

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

1.2 Понятие переменной

Переменные вводятся в программу для хранения и передачи данных внутри нее. Все переменные, которые предполагается использовать в программе должны, прежде всего, быть определены в разделе описания переменных. Описание переменных начинается со служебного слова VAR, вслед за которым располагается последовательность самих определений переменных.  Определение переменной заключается в указании ее имени (идентификатора) и типа. Имя и тип разделяются двоеточием. После объявления и описания переменной должен стоять символ ";". Концом блока описания будет начало какого-либо другого блока программы или описание процедур и функций.

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

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

Как правило, универсальный исполнитель имеет собственную память, и выполнение им команд может приводить не к каким-либо внешним действиям, а к изменению его внутреннего состояния. Например, используя сигналы от датчика фазы, компьютер автомобиля вычисляет текущие обороты двигателя (которые показывает на тахометре). Используя эти данные и информацию, поступающую от датчика скорости автомобиля, компьютер может вычислить, какая передача включена в определенный момент времени. Далее вычисляется текущая нагрузка на двигатель и устанавливается, какой должна быть смесь бензина и воздуха, подаваемая в цилиндры двигателя. В зависимости от этого подаются команды на открытие форсунок. От степени обогащения смеси зависит момент зажигания - чем богаче смесь, тем позже момент зажигания; таким образом, подаче команды модулю зажигания предшествуют достаточно сложные вычисления.

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

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

Каждой переменной присваивается имя. В рассмотренном примере используются переменные " скорость ", " обороты двигателя ", " передача ", " нагрузка ", " температура ", " обогащенность смеси ", " угол опережения зажигания " и другие. С каждой переменной связан ее тип, т.е. множество значений, которое она может принимать. Например, " передача " принимает целые значения от 1 до 5 (обратная и первая передачи не различаются), тогда как " скорость ", а также " обогащенность смеси " принимают вещественные значения (скорость измеряется в м/сек, обогащенность смеси может измеряться либо соотношением кислорода и паров бензина в единице объема, либо в процентах относительно стехиометрической смеси 14/1, соответствующей полному сгоранию паров бензина).

С переменной можно выполнять два действия:

  1. прочитать текущее значение переменной;
  2. записать новое значение в переменную или, как говорят программисты, присвоить новое значение переменной.

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

имя переменной := выражение;

Знак := читается как присвоить значение. Во многих языках вместо него используется просто знак равенства:

имя переменной = выражение;

При выполнении оператора присваивания сначала вычисляется значение выражения в правой части, затем оно записывается в переменную, имя которой указано в левой части. Старое значение переменной при этом стирается. Например, скорость автомобиля вычисляется по количеству импульсов от датчика скорости в единицу времени: датчик скорости посылает 6 импульсов на каждый пройденный метр.

скорость := число импульсов от датчика скорости /(6 * интервал времени);

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

скорость := скорость * 3600 / 1000;

Здесь переменная " скорость " входит как в правую, так и в левую части оператора присваивания. В правой части используется старое значение этой переменной, вычисленное в м/сек. Поскольку час содержит 3600 секунд, то при домножении на 3600 получается расстояние в метрах, проходимое за 1 час; после деления на 1000 получается расстояние в километрах. Вычисленное значение затем присваивается переменной " скорость ".

Суммируем вышесказанное:

Универсальный исполнитель, или компьютер, - это исполнитель, который может управлять другими исполнителями. Запись алгоритма для универсального исполнителя может включать команды, которые он должен передать подчиненным исполнителям, и команды, изменяющие внутреннее состояние самого универсального исполнителя;

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

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

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

имя переменной := выражение;

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

1.3 Типы переменных

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

Целочисленные переменные

Тип целое число является основным для любого алгоритмического языка. Связано это с тем, что содержимое ячейки памяти или регистра процессора можно рассматривать как целое число. Адреса элементов памяти также представляют собой целые числа, с их помощью записываются машинные команды и т.д. Символы представляются в компьютере целыми числами - их кодами в некоторой кодировке. Изображения также задаются массивами целых чисел: для каждой точки цветного изображения хранятся интенсивности ее красной, зеленой и синей составляющей (в большинстве случаев - в диапазоне от 0 до 255 ). Как говорят математики, целые числа даны свыше, все остальное сконструировал из них человек.

Общепринятый в программировании термин целое число или целочисленная переменная, строго говоря, не вполне корректен. Целых чисел бесконечно много, десятичная или двоичная запись целого числа может быть сколь угодно длинной и не помещаться в области памяти, отведенной под одну переменную. Целая переменная в компьютере может хранить лишь ограниченное множество целых чисел в некотором интервале. В современных компьютерах под целую переменную отводится 4 байта, т.е. 32 двоичных разряда. Она может хранить числа от нуля до 2 в 32-й степени минус 1.

232 - 1 = 4294967295

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

a+b = b+a, ab = ba

(a+b) + c = a+(b+c), (ab)c = a(bc)

a(b+c) = ab+ac

Кольцо вычетов по модулю m

Целочисленный тип компьютера в точности соответствует важнейшему понятию математики - понятию кольца вычетов по модулю m. В качестве m выступает число 232 = 4294967296. В математике кольцо Zm определяется следующим образом. Все множество целых чисел Z разбивается на m классов, которые называются классами эквивалентности. Каждый класс содержит числа, попарная разность которых делится на m. Первый класс содержит числа

{...,-2m,-m,0,m,2m, ...}

второй

{..., -2m+1, -m+1, 1, m+1, 2m+1, ...}

последний

{..., -m-1, -1, m-1, 2m-1, 3m-1, ...}

Элементами кольца Zm являются классы эквивалентности. Их ровно m, так что, в отличие от множества целых чисел Z, кольцо Zm содержит конечное число элементов. Операции с классами выполняются следующим образом: надо взять по одному представителю из каждого класса, произвести операцию и определить, в какой класс попадает результат. Этот класс и будет результатом операции. Легко показать, что он не зависит от выбора представителей.

Все числа, принадлежащие одному классу эквивалентности, имеют один и тот же остаток при делении на m. Таким образом, класс эквивалентности однозначно определяется остатком от деления на m. Традиционно остаток выбирается неотрицательным, в диапазоне от 0 до m-1. Остатки используют для обозначения классов, при этом используются квадратные скобки. Так, выражение [5] обозначает класс эквивалентности, состоящий из всех чисел, остатки которых при делении на m равны пяти. Все кольцо Zm состоит из элементов

[0],[1],[2], ...,[m-1],

например, кольцо Z5 состоит из элементов

[0],[1],[2],[3],[4].

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

3%5 = 3,

17%5 = 2,

(-3)%5 = 2,

(-17)%5 = 3.

Отсюда видно, что в школьной математике не выполняется равенство

(-a)%b = -(a%b),

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

3%5 = 3,

17%5 = 2,

(-3)%5 = -3,

(-17)%5 = -2.

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

(-a)%b = a%(-b) = -(a%b)

справедливо. Это позволяет во многих алгоритмах не следить за знаками (так же, как в тригонометрии формулы, выведенные для углов, меньших 90 градусов, автоматически оказываются справедливыми для любых углов).

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

0,1,2,3, ...m-1.

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

k = целая часть(m/2)

тогда симметричная система остатков при нечетном m состоит из элементов

-k, -k+1, ..., -1, 0, 1, ..., k-1, k,

а при четном m - из элементов

-k, -k+1, ..., -1, 0, 1, ..., k-1.

Например, при m = 5 симметричная система остатков состоит из элементов

-2, -1, 0, 1, 2.

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

1+1 = 2, 1+2 = -2,

1+(-2) = -1, 1+(-1) = 0,

(-2)+2 = 0, (-2)+(-2) = 1.

Интерпретация положительных и отрицательных чисел

В кольце вычетов невозможно определить порядок, согласованный с операциями (т.е. так, чтобы, к примеру, сумма двух положительных чисел была положительной). Таким образом, в компьютере нет, строго говоря, положительных и отрицательных целых чисел, поскольку компьютерные целые числа - это на самом деле элементы кольца вычетов. Выбирая либо неотрицательную, либо симметричную систему остатков, можно интерпретировать эти числа либо как неотрицательные в диапазоне от нуля до m-1, либо как отрицательные и положительные числа в диапазоне от -k до k, где k - целая часть от деления m на 2.

В программировании симметричная система остатков более популярна, поскольку трудно обойтись без отрицательных чисел. При этом следует понимать, что сумма двух положительных чисел может оказаться отрицательной, или, наоборот, сумма двух отрицательных чисел - положительной. Иногда в программировании такую ситуацию называют переполнением. Привычные свойства целочисленных операций в компьютере выполняются лишь для небольших чисел, когда результат операции не превосходит числа m = 232. В случае целочисленных переменных переполнение не является экстраординарной ситуацией и не приводит к аппаратным ошибкам или прерываниям. (Это, кстати, отличает компьютерные целые числа от вещественных.) Переполнение - совершенно нормальная ситуация, если вспомнить, что компьютер работает с элементами кольца вычетов по модулю m, а не с настоящими целыми числами.

Следует также отметить, что симметричная система остатков кольца Zm в случае четного m (а m для компьютера равно 232, т.е. четно) не вполне симметрична. Поскольку ноль не имеет знака, то число положительных остатков не может равняться числу отрицательных.

Какой остаток выбрать в классе эквивалентности числа k = m/2? Для этого элемента выполняется непривычное с точки зрения школьной математики равенство

k + k  0( mod m),

т.е.

k  -k( mod m)

Как отрицательный остаток -k, так и положительный k в равной мере подходят для представления этого класса эквивалентности. По традиции выбирается отрицательный остаток. Таким образом, в компьютере количество отрицательных целых чисел на единицу больше, чем количество положительных. Так как m = 232 = 4294967296, то k = 231 = 2147483648, и симметричная система остатков состоит из элементов

-2147483648, -2147483647, ..., -2, -1, 0, 1, 2, ..., 2147483647.

В двоичном представлении старший разряд у отрицательных целых чисел равен единице, у положительных - нулю. Двоичные разряды представления целого числа в программировании нумеруют от 0 до 31 справа налево. Старший разряд имеет номер 31 и часто называется знаковым разрядом. Таким образом, знаковый разряд равен единице у всех отрицательных чисел и нулю у неотрицательных. Двоичное представление максимального по абсолютной величине отрицательного числа k состоит из единицы и тридцати одного нуля:

-214748364810 = 10000000000000000000000000000000

Двоичное представление числа -1 состоит из тридцати двух единиц:

-110 = 11111111111111111111111111111111

Двоичное представление максимального положительного числа состоит из нуля в знаковом разряде и тридцати одной единицы:

214748364710 = 01111111111111111111111111111111

Следует отметить, что в программировании часто используют также короткие целые числа, двоичная запись которых занимает восемь разрядов, т.е. один байт, или шестнадцать разрядов, т.е. два байта. Работа с такими короткими целыми числами поддерживается на аппаратном уровне. В языке Си однобайтовым целым числам соответствует тип char (тип char в Си - это именно целые числа, символы представляются их целочисленными кодами), двухбайтовым - тип short. Однобайтовые целые числа - это элементы кольца вычетов Zm, где m = 28 = 256. Симметричная система остатков в этом случае состоит из элементов

-128, -127, ..., -2, -1, 0, 1, 2, ..., 127.

В случае двухбайтовых целых чисел (тип short ) m = 216 = 65536, а симметричная система остатков состоит из элементов

-32768, -32767, ..., -2, -1, 0, 1, 2, ..., 32767.

Вещественные переменные

Вещественные числа представляются в компьютере в так называемой экспоненциальной, или плавающей, форме. Вещественное число r имеет вид

r = ±2e × m

Представление числа состоит из трех элементов:

  1. знак числа - плюс или минус. Под знак числа отводится один бит в двоичном представлении, он располагается в старшем, т.е. знаковом разряде.

Единица соответствует знаку минус, т.е. отрицательному числу, ноль - знаку плюс. У нуля знаковый разряд также нулевой;

  1. показатель степени e, его называют порядком или экспонентой. Экспонента указывает степень двойки, на которую домножается число. Экспонента может быть как положительной, так и отрицательной (для чисел, меньших единицы). Под экспоненту отводится фиксированное число двоичных разрядов, обычно восемь или одиннадцать, расположенных в старшей части двоичного представления числа, сразу вслед за знаковым разрядом;
  2. мантисса m представляет собой фиксированное количество разрядов двоичной записи вещественного числа в диапазоне от 1 до 2:

1 <= m<2

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

В языке Си вещественным числам соответствуют типы float и double. Элемент типа float занимает 4 байта, в которых один бит отводится под знак, восемь - под порядок, остальные 23 - под мантиссу (на самом деле, в мантиссе 24 разряда, но старший разряд всегда равен единице, поэтому хранить его не нужно). Тип double занимает 8 байтов, в них один разряд отводится под знак, 11 - под порядок, остальные 52 - под мантиссу. На самом деле в мантиссе 53 разряда, но старший всегда равен единице и поэтому не хранится. Поскольку порядок может быть положительным и отрицательным, в двоичном коде он хранится в смещенном виде: к нему прибавляется константа, равная абсолютной величине максимального по модулю отрицательного порядка. В случае типа float она равна 127, в случае double - 1023.

Основным типом является тип double, именно он наиболее естественен для компьютера. В программировании следует по возможности избегать типа float, так как его точность недостаточна, а процессор все равно при выполнении операций преобразует его в тип double. (Один из немногих случаев, где применение типа float оправдано, - трехмерная компьютерная графика.)

Несколько примеров представления вещественных чисел в плавающей форме:

1.0 = +20*1.0

Здесь порядок равен 0, мантисса - 1. В двоичном коде мантисса состоит из одних нулей, так как старший разряд мантиссы (всегда единичный) в коде отсутствует. Порядок хранится в двоичном коде в смещенном виде, он равен 127 в случае float и 1023 в случае double ;

3.5 = +21*1.75

Порядок равен единице, мантисса состоит из трех единиц, из которых в двоичном коде хранятся две: 1100...0 ; смещенный порядок равен 128 для float и 1024 для double ;

0.625 = +2-1*1.25

Порядок отрицательный и равен -1, дробная часть мантиссы равна 0100...0 ; смещенный порядок равен 126 для float и 1022 для double ;

100.0 = +26*1.5625

Порядок равен шести, дробная часть мантиссы равна 100100...0 ; смещенный порядок равен 133 для float и 1029 для double.

При выполнении сложения двух положительных плавающих чисел происходят следующие действия:

  1. выравнивание порядков. Определяется число с меньшим порядком. Затем последовательно его порядок увеличивается на единицу, а мантисса делится на 2, пока порядки двух чисел не сравняются. Аппаратное деление на 2 соответствует сдвигу двоичного кода мантиссы вправо, так что эта операция выполняется быстро. При сдвигах правые разряды теряются, из-за этого может произойти потеря точности (в случае, когда правые разряды ненулевые);
  2. сложение мантисс;
  3. нормализация: если мантисса результата стала равна или превысила двойку, то порядок увеличивается на единицу, а мантисса делится на 2. В результате этого мантисса попадает в интервал 1 <= m<2. При этом возможна потеря точности, а также переполнение, когда порядок превышает максимально возможную величину.

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

Машинный эпсилон

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

a + b = b ≠ 0

Более того, для сложения не выполняется закон ассоциативности:

a + (b + c) ≠ (a + b) + c

Действительно, пусть ɛ - максимальное плавающее число среди чисел, удовлетворяющих условию

1.0 + ɛ = 1.0

(приведенные выше рассуждения показывают, что такие числа существуют). Тогда

(1.0 + ɛ) + ɛ≠1.0 +(ɛ + ɛ)

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

Число ɛ часто называют машинным эпсилоном или, чуть менее корректно, машинным нулем, поскольку при прибавлении к единице оно ведет себя как ноль. Величина машинного эпсилона характеризует точность операций компьютера. Она примерно одинакова для всех современных компьютеров: большинство процессоров работают с восьмибайтовыми плавающими числами (тип double в Си), а арифметика плавающих чисел подчиняется строгим международным стандартам.

Оценим величину машинного эпсилона для типа double. Число 1.0 записывается в плавающей форме как

1.0 = +20*1.0.

Порядок плавающего числа 1.0 равен нулю. При сложении 1.0 с числом ɛ производится выравнивание порядка путем многократного сдвига мантиссы числа ɛ вправо и увеличения его порядка на 1. Поскольку все разряды числа ɛ  должны в результате выйти за пределы разрядной сетки, должно быть выполнено 53 сдвига. Порядок числа ɛ  после этого должен стать равным порядку числа 1.0, т.е. нулю. Следовательно, изначально порядок числа ɛ  должен быть равным -53:

ɛ = 2-53m

где m - число в диапазоне от единицы до двух. Таким образом, величина машинного эпсилона составляет примерно

2-53 ≈10-16

Приблизительно точность вычислений составляет 16 десятичных цифр. (Это также можно оценить следующим образом: 53 двоичных разряда составляют примерно 15.95 десятичных, поскольку 53/log210≈53/3.321928 ≈15.95.)

В случае четырехбайтовых плавающих чисел (тип float языка Си) точность вычислений составляет примерно 7 десятичных цифр. Это очень мало, поэтому тип float чрезвычайно редко применяется на практике. К тому же процессор сконструирован для работы с восьмибайтовыми вещественными числами, а при работе с четырехбайтовыми он все равно сначала приводит их к восьмибайтовому типу. В программировании следует избегать типа float и всегда пользоваться типом double.

Некоторые процессоры применяют внутреннее представление плавающих чисел с большим количеством разрядов мантиссы. Например, процессор Intel использует 80-битовое (десятибайтовое) представление. Поэтому точность вычислений, которые не записывают промежуточные результаты в память, может быть несколько выше указанных оценок.

Кроме потери точности, при операциях с вещественными числами могут происходить и другие неприятности:

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

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

  1. бесконечно большое число - это плавающее число с очень большим положительным порядком и, таким образом, очень большое по абсолютной величине. Оно может иметь знак плюс или минус;
  2. бесконечно малое, или денормализованное, число - это ненулевое плавающее число с очень большим отрицательным порядком (т.е. очень маленькое по абсолютной величине);
  3. Not a Number, или NaN - двоичный код, который не является корректным представлением какого-либо вещественного числа.

Любые операции с константой NaN приводят к прерыванию, поэтому она удобна при отладке программы - ею перед началом работы программы инициализируются значения всех вещественных переменных. Если в результате ошибки программиста при вычислении выражения используется переменная, которой не было присвоено никакого значения, то происходит прерывание из-за операции со значением NaN и ошибка быстро отслеживается. К сожалению, в случае целых чисел такой константы нет: любой двоичный код представляет некоторое целое число.

Запись вещественных констант

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

1.2, 0.725, 1., .35, 0.

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

Экспоненциальная форма записи вещественной константы содержит знак, мантиссу и десятичный порядок (экспоненту). Мантисса - это любая положительная вещественная константа в форме с фиксированной точкой или целая константа. Порядок указывает степень числа 10, на которую домножается мантисса. Порядок отделяется от мантиссы буквой "e" (от слова exponent), она может быть прописной или строчной. Порядок может иметь знак плюс или минус, в случае положительного порядка знак плюс можно опускать. Примеры:

1.5e+6 константа эквивалентна 1500000.0

1e-4 константа эквивалентна 0.0001

-.75E3 константа эквивалентна -750.0

Глава 2. Практическое использование переменных в программировании

Структура исходной программы на ЯП. Исходная программа (source module), как правило, состоит из следующих частей (впервые эти требования были сформулированы в языке Cobol):

  • раздела идентификации — области, содержащей наименование программы, а также дополнительную информацию для программистов и/или пользователей;
  • раздела связи — фрагмента текста, описывающего внешние переменные, передаваемые вызывающей программой (если таковая имеется), т. е. ту часть исходных данных, которая обязательно поступает на вход программы при ее запуске. Эти переменные часто называют параметрами программы;
  • раздела оборудования (среды) — описания типа ЭВМ, процессора, требований к оперативной и внешней памяти, существенных с точки зрения выполнимости программы. Дело в том, что даже среди семейства однотипных ЭВМ могут существовать отличия в наборе машинных инструкций (команд), средств программирования ввода-вывода, кодированного представления данных, в связи с этим описание среды, приводимое в данном разделе, оказывается необходимым транслятору с языка с точки зрения оптимизации выполнения или вообще оценки возможности создания рабочей программы;
  • раздела данных — идентификации (декларации, объявления, описания) переменных, используемых в программе, и их типов. Понятие типа позволяет осуществлять проверку данных на совместимость в операциях еще на этапе трансляции программы и отвергнуть недопустимые преобразования;
  • раздела процедур — собственно программной части, содержащей описание процессов обработки данных. Элементами процедуры являются операторы и стандартные функции, входящие в состав соответствующего языка программирования.

Необходимо отметить, что конкретные ЯП могут не требовать наличия всех выше перечисленных разделов исходного модуля. В некоторых случаях описания переменных могут размещаться произвольно в тексте или опускаться, при этом тип переменной определяется компилятором, исходя из системы умолчаний; есть средства программирования, в которых тип переменной задается в момент присвоения ей значения другой переменной или константы и т. д. Существуют фрагменты описания данных, которые могут быть отнесены как к разделу данных, так и к разделу оборудования (указания на устройство, длину и формат записи, организацию файла и т. п.).

Операторы ЯП. К типовым операторам управления вычислительным процессом относятся следующие:

    • организация циклов (выполняемых до исчерпания списка или до достижения управляющей переменной заданного значения, или пока выполняются некоторые условия);
    • ветвление программы — выполнение альтернативных групп операторов при заданных условиях;
    • блоки операторов — группы, выполняемые как целое;
    • операторы перехода — условная или безусловная передача управления на определенный оператор, снабженный меткой, или условный/безусловный выход из цикла или блока.

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

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

Операторы присваивания значений выполняют следующие функции:

  • пересылку значений переменных, констант, функций в принимающую переменную;
  • вычисление значений арифметической (числовой) переменной в рамках существующих в языке правил построения арифметических выражений (обычно включающих символы «()» — скобки, «+» — сложение, «-» — вычитание, «/» — деление, «*» — умножение, «**» или «л» — возведение в степень);
  • вычисление значений строчной (символьной) переменной путем соединения, пересечения, вычисления строк;
  • вычисление логических переменных в рамках правил образования логических выражений (обычно включающих скобки и операции и, или, не).

Аналогично могут быть выделены типичные группы функций:

    • стандартные алгебраические и арифметические — sin, Cos, Sqrt, Min, Max И Др.;
    • стандартные строчные — выделение, удаление подстроки, проверка типа переменной и т. д.;
    • нестандартные функции, в том числе описание операций и форматов ввода-вывода данных; преобразование типов данных; описание операций над данными, специфичными для конкретной системы программирования, ОС или типа ЭВМ.

2.1. Подпрограммы

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

Как уже упоминалось выше, первоначально наборы таких программных заготовок именовались библиотеками стандартных программ (БСП).

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

Объявления (типы, переменные, константы), использующиеся любой подпрограммой, относятся к одной из двух категорий — категории локальных объявлений и категории глобальных объявлений.

Локальные объявления принадлежат подпрограмме, описаны внутри нее и могут использоваться только ею.

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

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

Описание подпрограммы может содержать список аргументов (параметров), которые называются формальными. Каждый параметр из списка формальных параметров является локальным по отношению к подпрограмме, для которой он объявлен. Это означает, что глобальные переменные, имена которых совпадают с именами формальных параметров, становятся недоступными для использования в подпрограмме.

Все формальные параметры можно разбить на две категории:

  • параметры, вызываемые подпрограммой по своему значению (т. е. параметры, которые передают в подпрограмму свое значение и не меняются в результате выполнения подпрограммы);
  • параметры, вызываемые подпрограммой по наименованию (т. е. параметры, которые становятся доступными для изменения внутри подпрограммы).

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

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

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

Элементы языков программирования могут рассматриваться на следующих уровнях:

  • алфавит — совокупность символов, отображаемых на устройствах печати и экранах и/или вводимых с клавиатуры терминала. Обычно это набор символов Latin-1, с исключением управляющих символов. Иногда в это множество включаются неотображаемые символы, с указанием правил их записи (комбинирование в лексемы);
  • лексика — совокупность правил образования цепочек символов (лексем), образующих идентификаторы (переменные и метки), операторы, операции и другие лексические компоненты языка. Сюда же включаются зарезервированные (запрещенные, ключевые) слова ЯП, предназначенные для обозначения операторов, встроенных функций и пр.
  • синтаксис — совокупность правил образования языковых конструкций, или предложений ЯП — блоков, процедур, составных операторов, условных операторов, операторов цикла и пр. Особенностью синтаксиса 4 является принцип вложенности (рекурсивность) правил построения конструкций;
  • семантика — смысловое содержание конструкций, предложений языка, семантический анализ — это проверка смысловой правильности конструкции. Например, если мы в выражении используем переменную, то она должна быть определена ранее по тексту программы, а из этого определения может быть получен ее тип. Исходя из типа переменной, можно говорит о допустимости операции с данной переменной. Семантические ошибки возникают при недопустимом использовании операций, массивов, функций, операторов и пр.

2.2. Написание простейшей программы на языке С

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

//Сложение двух чисел

#include <iostream>

using namespace std;

int main()

{

int chislo1;

int chislo2;

int summa;

cout << "Vvedite pervoe chislo: " << endl;

cin >> chislo1;

cout << "Vvedite vtoroye chislo: " << endl;

cin >> chislo2;

summa = chislo1 + chislo2;

cout << "Summa ravna: " << summa << endl;

return 0;

}

Давайте теперь разберем код, а затем вы создадите новый проект в среде программирования, напишите эту программу, откомпилируете и построите, запустите и сами посмотрите на результаты ее работы. Итак, первая строка – это однострочный комментарий - в нем мы указываем цель нашей программы (у нас она складывает два числа). В случае, если он не помещается на одну строку, то перед тем, как его продолжать писать на новой строке, нужно опять поставить две косые черты, предваряющие комментарий "//". Есть в С++ и многострочный комментарий, пришедший из более раннего языка Си, но им пользуются реже. Вот так он выглядит:

/* здесь вы вводите

текст своего комментария, который

может состоять из нескольких строк,

вот как в этом примере, и ограждается он с двух сторон

вот такими обозначениями */

Этот же текст с использованием однострочного комментария выглядел бы так:

//здесь вы вводите

//текст своего комментария, который

//может состоять из нескольких строк,

//вот как в этом примере, и ограждается он с двух сторон

//вот такими обозначениями

Следующая строка кода - это уже известная нам директива препроцессора, подключающая необходимый для работы заголовочный файл iostream.h. Подключаем его, т.к. у нас используются в программе функции вывода (cout), ввода (cin), перевода курсора на новую строку (endl), объявленные в нем.

Далее мы видим главную и обязательную функцию программы - main(). С ней то и начинается построчное выполнение программы. Построчное, потому что в программировании все инструкции выполняются последовательно, если не задано иных условий.

Первая строчка программы - int chislo1; Это и есть наша первая переменная, а если быть точнее, то ее объявление в программе. Прежде, чем использовать какую-либо переменную в программе, ее нужно объявить.

Объявить - значит определить тип и присвоить имя. В нашем случае мы определили тип нашей переменной, как int (то есть целое число), а имя дали chislo1. Для чего при объявлении переменных нужно указывать тип!? Для того, чтобы программа при запуске смогла зарезервировать в оперативной памяти компьютера столько места, сколько необходимо для ее хранения. Для хранения целого числа типа int требуется 4 байта оперативной памяти. Размер такого числа может быть в пределах от чуть более +2 млрд. до чуть более, чем -2 млрд.

Объявить переменную можно в любом месте программы, до ее первого использования. Хотя желательно в своих программах придерживаться какого-либо одного стиля: например, объявлять в начале функции main(), как в этой программе.

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

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

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

int chislo1;

int chislo2;

int summa;

Можно также объявить эти переменные и в одну строку, т.к. их типы совпадают. Получится так:

int chislo1, chislo2, summa;

Итак, сначала нужно указать тип переменной. В нашем случае - это тип "int", целочисленная переменная. Затем указывается имя переменной и ставится точка с запятой, т.к. мы знаем, что каждая инструкция в языке С++ заканчивается точкой с запятой. Переменные мы объявили, соответственно, место для них в памяти компьютера уже будет зарезервировано. Но есть одно но...переменным еще не присвоено значение, поэтому различные операции (сложение, вычитание, сравнение и т.д.) с ними производить еще нельзя. В них содержится различный "мусор" (ненужные значения). Поэтому смотрим следующие строки:

cout << "Vvedite pervoe chislo: " << endl;

cin >> chislo1;

cout << "Vvedite vtoroye chislo: " << endl;

cin >> chislo2;

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

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

summa = chislo1 + chislo2;

Здесь мы видим оператор присваивания "=" и оператор сложения "+". Что они делают, я думаю, что вы уже догадались. Запомните только одну вещь: в отличие от математики в программировании знак присваивания ("=") работает чуть по другому - то, что находится справа от него, присваивается той переменной, что слева. Т.е. сначала складываются две переменные chislo1 и chislo2, а затем их результат записывается в переменную summa. Теперь можно пользоваться этой переменной, что мы и сделаем в следующей строке кода.

Следующая строка кода выводит значение этой переменной на экран:

cout << "Summa ravna: " << summa << endl;

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

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

ЗАКЛЮЧЕНИЕ

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

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

СПИСОК ЛИТЕРАТУРЫ

Григорьев, А.Б. О чем не пишут в книгах по Delphi; БХВ-Петербург - Москва, 2013. - 576 c.

Гудман, Д. JavaScript и DHTML. Сборник рецептов для профессионалов; СПб: Питер - Москва, 2013. - 523 c.

Доорс, Дж.; Рейблейн, А.Р.; Вадера, С. Пролог - язык программирования будущего; М.: Финансы и статистика - , 2011. - 144 c.

Дунаев, Вадим Web-программирование для всех; БХВ-Петербург - Москва, 2013. - 560 c.

Дьяконов, В.П. Справочник по расчетам на микрокалькуляторах; М.: Наука. Главная редакция Физико-математической литературы - Москва, 2011. - 464 c.

Ерофеев, В.И.; Меркушов, Ю.П. и др. Средства отладки программ в ОС ЕС; Статистика - Москва, 2012. - 245 c.

Кристиансен, Том; Торкингтон, Натан Perl: библиотека программиста; СПб: Питер - Москва, 2013. - 736 c.

Ламот, А. Программирование трехмерных игр для Windows; Вильямс - Москва, 2011. - 920 c.

Либерти, Джесс Освой самостоятельно C++ за 21 день; М.: Вильямс - Москва, 2012. - 816 c.

Коляда М. Г. Окно в удивительный мир информатики. – Д.: Сталкер, 1997.

Немнюгин С. А. Turbo Pascal: практикум. – СПб: Питер, 2003.

Лекция 1: Программирование - основные понятия. URL: https://www.intuit.ru/studies/courses/672/528/lecture/11894 . (Дата обращения 15.04.2020)