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

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

ВВЕДЕНИЕ

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

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

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

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

- рассмотреть теоретические аспекты исследования переменных в программировании;

- изучить отличие переменной от константы.

Объект исследования - переменные.

Предмет исследования - исследование понятие переменной в программировании, виды и типы переменных.

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

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

ГЛАВА 1 Теоретические аспекты исследования переменных в программировании

1.1 Понятие и типы переменных

Переменная - это одно из важнейших понятий при изучении любого языка программиро­вания. На первый взгляд может показаться, что оно простое и не нуждается в разработке какой- то специальной методики изложения. Однако внимательный анализ опыта преподавания пока­зывает, что для студентов, сталкивающихся с переменными во вводных курсах программирова­ния, формирование эффективных представлений о переменных оказывается весьма сложной за­дачей. В частности, как следует из описанных в [13] экспериментов, только 40-50 % от общего числа студентов при выполнении анализа коротких фрагментов программ демонстрируют пол­ностью правильное понимание работы с переменными.

В известной статье [9], посвященной анализу трудностей в изучении основ программиро­вания, описан ряд заблуждений, которые могут возникать у учеников в случае непродуманного изложения материала. В частности, негативные эффекты часто являются следствием чрезмерно­го увлечения примитивными бытовыми аналогиями без глубоких объяснений. Когда ученикам представляют переменную в виде коробочки или выдвижного ящичка, где снаружи наклеена этикетка с именем, есть опасность, что их живое воображение сформирует неправильный вывод о сохранении в переменной полного списка всех когда-либо присвоенных ей значений или при­ведет к ложному убеждению о возможности одновременного сохранения в таком контейнере не­скольких значений переменной. Более того, образ ящичка у некоторых учеников неожиданным образом формирует уверенность, что если в переменную еще не помещено никакое значение, то оно равно нулю, поскольку пустая емкость воспринимается как разновидность нулевого зна­чения.

В то же время обходиться в обучении совсем без моделей абстрактных понятий тоже не лучший вариант. Даже если учитель не предложил на уроке никакой модели, она все равно стихийно формируется в сознании учащихся [9]. Пока все идет хорошо, это не имеет особого значения. Но при анализе возникших ошибок некорректность внутренней ментальной модели часто проявляет себя. Сошлемся здесь также на мнение М. Бен-Ари, который, проанализировав роль ментальных моделей в усвоении учебного материала, пришел к выводу, что при объясне­нии абстрактных понятий обязательно требуется сформулировать подходящую модель на один уровень ниже, чем вы учите сейчас [7]. Применительно к нашему случаю это означает, что мо­дель устройства переменной при объяснении материала необходима.

Значение рассматриваемой проблемы в настоящее время существенно возрастает, по­скольку типы и структура переменных становятся все более сложными, и, следовательно, пра­вильно их себе представить становится все труднее. В частности, для переменных, которые яв­ляются объектами, возникают дополнительные специфические проблемы при усвоении мате­риала [12].

Можно привести и еще один факт, подтверждающий потребность в совершенствовании методики формирования рассматриваемого понятия. Для облегчения усвоения применения пере­менных финские преподаватели предложили показывать новичкам все основные роли перемен­ных, которые встречаются в программах [15]. Оказалось, что для описания почти 99 % случаев использования переменных в классическом языке вроде Паскаля достаточно всего десяти ролей. В то же время для более современного языка Питон список ролей пришлось усовершенствовать [14], что подтверждает изменение концепций использования переменных в новых языках.

Реализация переменных в разных языках программирования может иметь свои особенно­сти. Авторы не ставили себе целью написать профессиональный обзор устройства трансляторов, а попытались отобрать и сформулировать наиболее важные и типичные сведения о хранении переменных на примере двух языков: классического Паскаля и современного языка Питон (Py­thon, по-английски правильнее читать «Пайтон»). Надеемся, что понимание описанных принци­пов будет полезно и при изучении других языков.

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

Переменная характеризуется:

  • Именем («обозначением ячейки памяти»)
  • Значением (данными, содержащимися в переменной в конкретный момент времени)
  • Типом (определяющим: а) какие значения может принимать переменная; б) какие операции можно производить с этими значениями; в) как данные представлены в памяти компьютера)

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

Простые типы

Дискретные (можно перечислить возможные значения):

  • целые (integer, longint)
  • символьный (char)
  • логический (boolean)
  • диапазон (часть значений стандартного дискретного типа, например, 1..100)
  • перечисляемый (явно перечислены все допустмые значения)

Вещественные (real, double, extended) — служат для представления действительных чисел с ограниченной точностью.

Структурированные типы

  • Массив (фиксированное количество данных одного типа)
  • Строка
  • Запись (связанные данные, в общем случае, разных типов)
  • Множество
  • Файл (данные одного типа, хранящиеся на внешнем носителе)

var 
  имена переменных : тип;
...
  имена переменных : тип;

Например:

var 
  a, b, c: real;
  i, n: integer;
  f: boolean;

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

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

read(переменные);

или

readln(переменные);

При выполнении оператора программа будет приостановлена, пока пользователь не наберет на клавиатуре значения и не нажмет клавишу «Enter». Затем введенные значения будут помещены в переменные, указанные как параметры процедуры ввода. Например, при выполнении оператора

read(a, b);

компьютер будет ожидать ввода двух значений, которые затем будут помещены в переменные a и b.

Операторы read и readln отличаются тем, что во втором случае после ввода данных будет переведена строка, т.е. последующие сообщения компьютера будут выводиться с новой строки.

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

write(выражения);

или

writeln(выражения);

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

write(a + b, c);

на экран будет выведена сумма переменных a и b, а также значение переменной c. Если нужно вывести на экран какое-либо текстовое сообщение, его нужно заключить в апострофы (одиночные кавычки):

write('Нет решения');

Операторы write и writeln отличаются тем, что во втором случае после вывода данных будет переведена строка, т.е. последующие сообщения компьютера будут выводиться с новой строки.

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

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

Тип переменной должен совпадать с типом выражения либо быть «более широким» совместимым (т.е. вещественной переменной можно присвоить значение целого выражения; строковой переменной можно присвоить значение символьного выражения).

Компьютер сначала вычисляет значение выражения в правой части оператора присваивания, затем помещает его в переменную, указанную слева от символа присваивания «:=».

Например, при выполнении оператора

x := a + b;

переменная x получит значение суммы переменных a и b. При выполнении оператора

n := n + 1

значение переменной n увеличится на единицу.

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

a := b;

b := a;

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

Рассмотрим, как составить простую программу, выполняющую какие-либо вычисления. Для этого нам нужно:

  1. Проанализировав условие задачи, выделить исходные данные и результаты. Выбрать для них имена переменных (если они не заданы в условии). Определить тип данных.
  2. Построить математическую модель задачи — описание в виде набора математических соотношений.
  3. Разработать (или подобрать из известных) алгоритм решения задачи — последовательность действий, приводящую от исходных данных к результатам за конечное число шагов. (Не забудьте, что сначала компьютер должен получить значения исходных данных, а после нахождения результатов — вывести эти результаты на экран).
  4. Если в процессе решения используются промежуточные данные, выбрать имена переменных и определить их тип.
  5. Записать программу в соответствии с правилами синтаксиса языка программирования (в нашем случае — Pascal).

Рассмотрим простейший пример.

Задача

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

Решение

1) Определим исходные данные и результаты задачи. В данном случае они явно указаны в условии: исходная величина — радиус, результаты — длина окружности и площадь круга. Используем для них традиционные обозначения: R, L и S, соответственно. Все эти переменные могут принимать как целые, так и дробные числовые значения, поэтому следует использовать вещественный тип данных, например, Real.

2) Математически задача описывается известными формулами:

L = 2 ⋅ π ⋅ R  
и S = π ⋅ R2   

3) Алгоритм в данном случае предельно прост:

  1. Ввести значение радиуса.
  2. Вычислить длину окружности по формуле [1].
  3. Вычислить площадь круга по формуле [2].
  4. Вывести значения длины окружности и площади круга на экран.

4) При вычислениях нам (точнее, компьютеру) потребуется значение π. Вообще говоря, практически все реализации Pascal имеют встроенную константу PI, но мы объявим подобную константу самостоятельно.

5) Теперь запишем программу:

program circle; { Имя программы можно выбирать произвольно }
{ В фигурных скобках записываем комментарии — этот текст компьютер пропускает }
  const p = 3.14159265358; { Объявление константы }
  var L, R, S: Real; { Все переменные одного тип }
begin
  write ('Введите величину радиуса:'); { Выводим на экран пояснение }
  readln (R); { Вводим значение и переходим на новую строку }
  L := 2 * p * R; { Операция умножения обязательно указывается! }
  S := p * R * R; { Можно записать S := p * sqr(R); }
  writeln ('L=', L:10:3, ' S=', S:10:3); { Выводим поясняющий текст }
  { и значения переменных. Для значений указан }
  { формат: всего 10 знаков, из них 3 — после точки. }
end.

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

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

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

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

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

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

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

Для статических массивов известной размерности, состоящих из однотипных элементов, картина качественно не меняется: значения элементов массива, скажем, числа, размещаются в памяти друг за другом. Адрес начала нужного значения вычисляется по несложной формуле, смысл которой состоит в пропуске необходимого числа байтов ОЗУ, в которых лежат все пре­дыдущие элементы массива.

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

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

  • переменные создаются при выполнении программы (а не при трансляции, как было в ста­тическом случае!);
  • под значения динамических переменных отведена специальная область памяти (ее часто называют heap - куча); работающая программа находит в ней свободное место и резер­вирует его под значение создаваемой переменной;
  • адрес выбранной области заносится в переменную; таким образом, в ней хранится не са­мо значение (как в статическом случае), а его адрес в ОЗУ; саму переменную, в которой хранится адрес, принято называть указателем;
  • если размер памяти, требуемой для хранения значения динамической переменной, не ме­няется, то новое значение, как вариант, может помещаться в те же самые ячейки ОЗУ;
  • если же размер значения динамической переменной меняется (например, в строку поме­щают текст большей длины), то остается единственная возможность: сначала создать но­вое значение, а затем указатель заменить на адрес этого значения; память со старым зна­чением автоматически будет освобождена[1];

• подчеркнем, что хотя местоположение значения динамической переменной может ме­няться в процессе выполнения программы, положение самих переменных-указателей ос­тается в ОЗУ неизменным.

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

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

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

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

Таким образом, возникает еще одно разделение переменных: на глобальные (доступные всем подпрограммам) и локальные (описанные в подпрограммах). Свойства этих двух видов переменных существенно отличаются. Глобальные переменные существуют в течение всего времени работы программы; их значения доступны (часто говорят «видны») из любой процеду­ры или функции. Локальные же переменные создаются в процессе работы подпрограммы, а при выходе из нее исчезают; очевидно, что вне процедуры ее переменные не видны.

В классических языках программирования локальные переменные организованы в памя­ти компьютера принципиально иначе, чем глобальные (реализация в Питоне требует отдельного обсуждения). Главная и не совсем очевидная причина появления этой разницы состоит в том, чтобы обеспечить возможность подпрограмме корректно вызывать другие подпрограммы и осо­бенно саму себя. Последний случай в программировании настолько востребован, что даже имеет специальное название - рекурсия. Рекурсия - это тема для самостоятельной статьи. Здесь же для нас важно, что если локальную переменную «привязать» к определенному адресу, то повторный вызов этой процедуры будет невозможным. В самом деле, при такой организации памяти локальные переменные при вложенном вызове подпрограмм просто совпадут; в результате одна из них потеряет свои значения. Поэтому для локальных переменных (а также для аргументов и результатов) используется особая организация памяти, гарантирующая корректное выполне­ние вложенных подпрограмм. Такая организация называется стеком.

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

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

Рассмотрим в качестве примера тип STRING в классическом Паскале[2]. Его значением является строка символов, каждый из которых занимает один байт. Главная проблема заключа­ется в том, что длина строки заранее неизвестна и компилятор языка программирования «не знает», сколько выделить памяти под строковую переменную. Классическое решение про­блемы было таким: по умолчанию под каждую строковую переменную отводилось 256 байт. Немедленно возникал вопрос: какая часть строки реально занята. Например, если присвоить переменной значение «ДОМ», то из всей отведенной памяти занято будет всего 3 байта. Было принято правило, что реально используемая длина строки хранилась в нулевом байте отведен­ной памяти. Поэтому нумерация символов начиналась с единицы, а длина строки не могла пре­вышать 255 байт. Для экономии памяти было разрешено создавать более короткие строки. На­пример, описание VAR s: STRING[5]; создавало в памяти строку из 5, а не из 255 символов.

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

Существуют и еще более сложные структуры данных. В частности, в Delphi и Visual BASIC имеется особый тип данных VARIANT, который может в разных участках программы помещать в одну и ту же переменную значения разного типа: например, сначала INTEGER, а затем STRING. В классическом Паскале такое вообще невозможно.

Рассмотрим кратко, как устроен это необычный тип данных в Delphi. Каждая переменная типа VARIANT состоит из 16 байт, причем первая их половина хранит служебную информа­цию, а вторая - значение переменной или ссылку на это значение. Самые первые 2 байта пере­менной содержат целое число, характеризующее тип значения, которое в данный момент лежит в переменной. Полный список возможных типов содержит около 20 разных значений, начиная с целых и вещественных чисел и кончая символьными строками и даже массивами. Например, для числа типа INTEGER характеристическое значение равняется 3, для вещественного числа типа DOUBLE - 5, а для STRING - 10016 = 25610.

Таким образом, внутри выделенной под переменную области ОЗУ кроме собственно зна­чения (или ссылки на него) есть еще служебная информация, в том числе и о типе текущего зна­чения. Благодаря такому устройству в переменную можно поместить значение любого допусти­мого типа. Но и это еще не все. Возможность изменять тип значения позволяет в нужных слу­чаях делать это автоматически. Например, если в результате арифметического действия ответ перестает помещаться в 2-байтовое целое, можно перейти к 4-байтовому. А когда «ассорти­мент» целых типов закончится, то вообще преобразовать результат в вещественное число. Пре­дусмотрены и более неожиданные преобразования типов. Например, если V1 и V2 типа VARI­ANT имеют значения V1=12.5, V2='12', то V1+V2 будет равно 24.5, потому что строка ‘12' пе­ред сложением будет автоматически преобразована в число.

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

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

В Питоне при обсуждении переменных вводится новое понятие - изменяемое (англ. mu­table) или неизменяемое (англ. immutable) значение. В первом случае переменная работает по классическому механизму, и новое значение записывается в ОЗУ на место старого. Так, напри­мер, устроен тип данных список, с помощью которого в Питоне моделируется массив. Во вто­ром случае новое значение создается в свободной области памяти, а затем в указатель записыва­ется новый адрес. Иными словами, хотя конкретное значение в памяти изменять нельзя, но зато можно переопределить ссылку на новое значение, хранимое в другом месте ОЗУ. Так работает большая часть типов в Питоне, в том числе все простые типы, в частности, числа и строки. В данном разделе мы будем обсуждать именно такие переменные.

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

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

Кроме того, в области памяти, отведенной под переменную и служебные данные о ней, хранится еще одно дополнительное число [4]. Понять его назначение можно на следующем про­стом примере. В Питоне можно присваивать одно и то же значение сразу нескольким перемен­ным. Например, x = y = z = 300.

После выполнения этой строки все переменные получат одно и то же значение. Задума­емся над вопросом, будут ли указатели в x, y и z одинаковыми, или же каждый из них будет показывать на «свое собственное» значение (вспомним, что при статическом методе организа­ции переменных в памяти действительно будут лежать три числа, равные 300). Оказывается [4, 6], в Питоне данная строка программы выполняется так: сначала создается числовое значение 300, а затем ссылка на него помещается во все три переменные. Если теперь поменять значения переменных, например, так

x = 1, y = 2, z = 3,

то все указатели будут переопределены на новое значение, а «утратившее силу» значение 300 станет ненужным.

Если подумать еще немного, то возникает следующий вопрос: а как программа узнает, в какой момент начальное значение перестанет быть нужным? В самом деле, после присвоения нового значения x ссылки в y и z еще остаются! Оказывается, решение проблемы очень простое: около каждого значения в памяти хранится счетчик количества ссылок на него. При изменении значения переменной ссылка переопределяется на новое значение, а из счетчика старого вычи­тается единица. В тот момент, когда счетчик обратится в ноль (в нашем примере это произойдет только после изменения указателя на переменную z), значение больше не используется и его можно удалить из памяти[3].

Итак, анализ показывает, что переменные в языках Паскаль и Питон существенно отли­чаются. В Паскале в переменной всегда хранится значение строго определенного типа. В Пито­не же тип переменной не фиксируется, и ей могут присваиваться значения произвольного типа (независимо от того, какое значение в переменной хранилось ранее, и даже существовала ли до этого данная переменная). Кроме того, в отличие от Паскаля, в Питоне большинство перемен­ных (в том числе все простые) динамические. Так что в переменной всегда располагается не са­мо значение, а ссылка на область ОЗУ, где находятся это значение и код его типа, а также счет­чик ссылок на данное значение.

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

• при написании и при наборе текста программы тщательно следить за правильностью имен переменных, иначе вместо одной переменной можно получить две разных[4] (см. пример 1 в разделе 6);

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

Совместное хранение в переменных значения и его типа позволяют интерпретатору Пи­тона обеспечивать более гибкую обработку данных. Рассмотрим это на примере целых чисел [11]. Пока значение числа невелико, оно хранится и обрабатывается обычным образом. Но (в последних версиях Питона) как только значение превысит допустимое для целых хотя бы на единицу, число автоматически преобразуется в новый формат: к его области хранения добавля­ется еще несколько байтов, и тем самым верхняя граница числового диапазона отодвигается. Переменная при этом получает другой тип, который обрабатывается по собственным правилам арифметики, заложенным в Питон-машину. Если и добавочных байтов становится недостаточ­но, то область хранения числа снова будет увеличена и т.д. Таким образом, количество битов для хранения числа все время автоматически добавляется и переполнения не происходит. Полу­чается, что величина целых чисел в Питоне ограничена только объемом свободной памяти.

Заметим, что указанный механизм автоматического расширения диапазона представле­ния целых чисел в Питоне на вещественные числа не распространяется (по крайней мере, пока).

1.2 Переменные в программировании

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

Переменная гибка:

  • в ней можно хранить информацию;
  • можно из неё извлекать информацию, что не повлияет на значение самой переменной;
  • в неё можно записать новые данные.

Причем, эти действия можно выполнять практически сколько угодно раз. Из названия ясно, что переменная – вещь непостоянная. Например, в языке программирования PHP переменные существуют или содержат в себе значение исключительно во время работы скрипта. Как только завершается исполнение скрипта, так и существование переменных прекращается. То есть при переходе с одной страницы web-сайта на другую, переменных и их значений прежней страницы уже нет. Это кроме случаев, когда нужные значения специально передаются другой странице.

Переменные появились с первыми языками программирования. Результат работы любой программы сводится к выполнению действий над какими-либо данными. Напомним, что память (memory) – это последовательность байтов (byte), каждый из которых принимает значения от 0 до 255. Так как байтов неимоверно много, единственный способ различать их - это присвоение каждому из них порядкового номера. Так и есть. Каждый байт оперативной памяти доступен процессору через его порядковый номер. Этот порядковый номер называется адресом байта.

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

С первыми языками программирования появилась полезная возможность связывания определенного участка оперативной памяти с символьным названием (набором символов). По сравнению с адресом название переменной может отражать содержимое этого участка памяти. Но имя переменной не единственная вещь, которая определяет переменную. Процессор может обрабатывать три вида данных: байт, слово и двойное слово[7;15].

(Термины «слово» и «двойное слово» здесь используются в узкоспециальном смысле, отражая собой размер участка памяти, выделенного под переменную.) Поэтому определение вида переменной в языках нижнего и среднего уровней происходит обычно указанием типа переменной. Эти два свойства переменной (название и тип) определяют нужный участок памяти и способ его использования. В большинстве случаев именно тип переменной определяет сколько байтов памяти захватит переменная. Например, переменной типа BYTE присвоено имя A. Процессор по названию переменной (А) определяет её место в памяти и при извлечении значения этой переменной воспользуется командой, предназначенной для извлечения байта (не слова и не двойного слова).

В общем случае, переменная – это поименованный участок оперативной памяти, используемый для временного хранения данных. В зависимости от языка программирования, объявление переменной может сопровождаться указанием его типа. Обычно в языках высокого уровня тип не указывается. Синтаксические различия между языками проявляются как раз в объявлении переменных. В C и C++ необходимо указывать тип, в PHP используется префикс $.

В современном мире программирования программист должен знать не только имя и тип переменной. Также существуют понятия пространства имен и область действия переменной. Представьте, что создается программа, в которой используются несколько переменных. Имена этих переменных составляют список, который определяет пространство имен. Представим, что в ходе создания программы мы, по ошибке, объявили две переменные с одинаковыми названиями. При попытке запуска программы его компилятор сообщит об этой ошибке. Это было бы невозможно, если бы компилятор не контролировал переменные. То есть контроль безупречности пространства имен возлагается от программиста на компилятор; что облегчает процесс создания и отладки программы. На практике, приведенный пример не во всех языках приводит к ошибке. Каждый компилятор (или интерпретатор) имеют собственные требования к пространству имен. То, что является ошибкой в одном языке (в данном случае C или C++), в других языках ошибкой может не быть.

Если раньше программы были небольшие и их исходный код располагался в одном файле, то сейчас текст кода может состоять из нескольких файлов. И запомнить уникальное имя каждой переменной, использующейся в программе, становится практически невозможным. Поэтому (и не только) было введено понятие области действия (или области существования) переменных. Область действия – понятие абстрактное. Это понятие применяется только в языках среднего и высокого уровней. Целью применения области действия является разделение пространства имен на несколько независимых частей. Так в программе могут существовать несколько переменных с одинаковыми именами и типами, не мешаю друг другу. Начинающему идея разделения области действия в пределах отдельных файлов исходного кода программы должна быть более понятна. Например, этот подход используется в PHP. Это означает, что переменная, объявленная в одном файле, может быть абсолютно недоступна в других файлах. Например, мы можем объявить переменную с именем MyVar в нескольких файлах проекта, и это не будет ошибкой.

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

1.3 Инкремент и декремент

Если необходимо изменить значение переменной на 1, то используют инкремент или декремент.

Инкремент - операция увеличения значения, хранящегося в переменной, на 1.

Пример:

x++; // значение переменной x будет увеличено на 1


Декремент - операция уменьшения значения, хранящегося в переменной, на 1.

Пример:

x--; // значение переменной x будет уменьшено на 1


Инкремент и декремент относятся к операциям присваивания. При использовании декремента и инкремента совместно с оператором присваивания "=" применяют постфиксную (x++) или префиксную (++x) запись. Первой выполняется префиксная запись.

Примеры:

y = x++;


Предположим, что в переменной x хранилось значение 5. Тогда в y будет записано значение 5, после чего значение переменной x будет увеличено на 1. Таким образом, в y будет 5, а в x - 6.

y = --x;


Если в x хранилось значение 5, то сначала будет выполнено уменьшение x до 4, а затем это значение будет присвоено переменной y. Таким образом, x и y будет присвоено значение 4.

ГЛАВА 2 ОТЛИЧИЕ ПЕРЕМЕННОЙ ОТ КОНСТАНТЫ

2.1 Калькулятор с константами

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

Согласитесь, что выражение
2 + 3 = 5
достаточно серьезно отличается от выражения:
a + b = c

В чем отличие? Не только в том, что в алгебре вместо цифр применяются буквы латинского алфавита, но отличие и в уровне абстракции.

Численные выражения, хоть что с ними делай, дают в итоге только численный результат. [14;157]

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

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

Так же и в компьютерной грамотности. Можно говорить сначала о самом низком уровне абстракции, например, об арифметике в программировании.

Калькуляторы дружат с константами

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

  • Вводим на калькуляторе первое число, например, «2»,
  • нажимаем на знак «плюс»,
  • вводим второе число, скажем, «3» (см. рис. 1),
  • и затем нажимаем знак «=».

Что получим? Очевидно, значение «5». Арифметика. Но с использованием компьютерной техники – калькулятора.

Рис. 1. Суммирование констант 2+3 на калькуляторе (Windows 7)

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

Рис. 2. Некоторые виды калькуляторов, имеющихся в Windows 7[7;25]

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

2.2 Программы с переменными величинами

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

Как это работает? Поясним несколько упрощенно, чтобы не требовалось глубокое погружение в сложную область программирования.

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

a + b = c,

то в программировании делают все наоборот: сначала указывают результат, а потом действие, то есть:

C = A + B.

Здесь не случайно я пишу строчные (заглавные) буквы вместо прописных (маленьких) букв:

во-первых, чтобы отличить алгебру от программирования, а

во-вторых, потому что первоначально в нашей стране в программировании использовали в основном заглавные буквы латинского алфавита.

Так как вместо прописных букв латиницы у нас делали строчную кириллицу, иначе где еще взять коды для русских букв?! Это связано с тем, что многие трансляторы с языков программирования у нас в стране лишь адаптировали с западных аналогов, а не разрабатывали с нуля. А там, откуда все это копировалось, русского языка не было по понятным причинам. Хотя были и примеры наших «родных» языков программирования.

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

Почему стали в программировании писать наоборот, а именно стали писать C = A + B? Трудно сказать. Так сложилось, что сначала надо было указывать результат, и лишь потом действие.

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

5 = 2 + 3 (напишем наоборот лишь для сравнения) и

C = A + B ?

Рис. 3 - Рисунок 2+3

Давайте разберемся. Что может быть результатом сложения 2+3? Большинство ответит, конечно, «5». И хоть это почти правильный ответ, пожалуй, мы с этим согласимся.

Почему почти? Да потому что это правильный ответ для десятичной системы исчисления. Для четверичной системы исчисления, в которой используются только цифры от 0 до 3, ответ был бы «11», да-да, именно одиннадцать, можете не сомневаться. А в пятеричной системе исчисления, где добавляется еще цифра 4, ответ был бы «10».

Но в любом случае, о какой бы системе исчисления мы не говорили, результатом 2+3 всегда будет одно и то же число (константа). В десятичной системе (вернемся к ней теперь надолго), это «5», и только «пять».

А сколько будет A + B? Ответ очевиден: все зависит от того, чему равны A и B. Значит, результатом 2+3 всегда будет 5, а результатом A+B будут разные значения в зависимости от величин A и B.

Достаточно очевидно. Ну и что, что 5 – константа, а тут переменная? А то, что переменные – это другой уровень абстракции. За счет A+B мы теперь можем получать множество разных значений[6;22].

Как могут использоваться выражения с переменными  величинами

Допустим, A – это вес одного товара, а B – это вес другого товара. Значит, A+B – это суммарный вес обоих товаров. Значит, используя выражение C=A+B, программист может запрограммировать автоматическое суммирование двух весов.

Как он это сделает?

  • Например, сначала программист попросит ввести с клавиатуры вес первого товара (не описываю, как это можно сделать в языке программирования, поверим, что так можно сделать), и присваивает введенное значение переменной с именем A.
  • Затем он проделывает то же самое с весом второго товара, и присваивает это уже переменной B.
  • А потом пишет в своей программе теперь уже понятное нам выражение:

C = A + B

Что получается в итоге? Конечно, вы сразу догадались, что переменной C будет присвоено значение суммы весов, сохраненных в переменных A и B.

И далее программист напишет в своей программе (тоже прошу поверить, что это можно сделать средствами языка программирования): вывести на экране дисплея значение переменной C. Что мы увидим на экране? Конечно, сумму весов первого и второго товаров!

И теперь эту, один раз написанную программу, можно использовать снова, но уже для суммирования следующей пары весов.

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

А если пойти дальше, и не выводить на экран сумму весов 2-х товаров, а записать это куда-то в базу данных?! А если не ограничиваться 2-я товарами, а, скажем, говорить о миллионе разных видов товаров, подлежащих взвешиванию? Почему бы и нет! Все это можно описать в виде выражений, подобных C = A + B.

И в итоге мы получим, можно без стеснения сказать, серьезную автоматизированную систему для супермаркета, где учитываются и веса всех товаров, и количество, и стоимость, а также все покупки, сделанные покупателями и прочее, и прочее и прочее. Но это стало возможным, когда появилось программирование с использованием переменных величин, тех самых A, B, C и тому подобное! Без этого уровня абстракции, без переменных не было бы программирования.

2.3 Переменные и константы

Справедливости ради, надо сказать, что цифры (простые и не очень простые числа) остались в программировании. Они тоже нужны. Их назвали иностранным словом «константы».

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

А что такое переменная в программировании?

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

Так что наряду с выражением C = A + B, в программировании возможно как выражение C = A + 3, так и C = 2 + B.

Однако в левой части программного выражения (до знака равенства «=») константа не может употребляться. Там может быть только переменная, поскольку значение выражения, которое присваивается переменной в левой части выражения, может меняться в зависимости от значений переменных в правой части выражения. А значит, слева может быть только переменная величина[3;15].

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

Чего стоило разработчикам языков программирования реализовать возможности для применения переменных величин? Это уже отдельная тема. Одно могу сказать, стоило дорого, само собой, не только в деньгах. Дорого в расходовании (применении) интеллекта для изобретения подобных вещей.

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

ЗАКЛЮЧЕНИЕ

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

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

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

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

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

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

  1. Александров В. В. Экологическая роль электромагнетизма. - СПб.: Изд-во Поли- техн. ун-та, 2015. - 736 с.
  2. Барабанов А. А., Косов А. А., Ярославцев Н. А. Влияние энергетических форм природы на жизнедеятельность человека // Академический вестник УралНИИпроект РААСН. - 2015. - № 1. - С. 91-96.
  3. Бугакова Т. Ю. Вовк И. Г. Математическое моделирование пространственно-временного состояния систем по геометрическим свойствам и оценка техногенного риска методом экспоненциального сглаживания // Вестник СГГА. - 2012. - Вып. 4 (20). - С. 47-58.
  4. Винер Н. Кибернетика, или управление и связь в животном и машине; или Кибернетика и общество. - 2-е издание. - М.: Наука; Главная редакция изданий для зарубежных стран, 2013. - 344 с.
  5. Галль Л. Н. В мире сверхслабых. Нелинейная квантовая биоэнергетика: Новый взгляд на природу жизни. - 2016. - 317 с.
  6. Гуревич И. М. Оценка основных информационных характеристик Вселенной // Приложение к журналу «Информационные технологии». - 2016. - № 12. - С. 2-17.
  7. Дубров А. П. Когнитивная психофизика: основы. - 2-е изд., исп. и доп. - Ростов н/Д.: Феникс, 2012. - 301 с.
  8. Егоров В. В. Физические поля и излучения организма (на примере человека). Проблемная лекция. - М.: ФГОУ ВПО МГАВМиБ, 2016. - 64 с.
  9. Информация // Большой энциклопедический словарь. - 2-е изд., перераб. и доп. - М.: Большая Российская энциклопедия, 2015. — 1434 с.
  10. Карпик А. П., Осипов А. Г., Мурзинцев П. П. Управление территорией в геоинформационном дискурсе. - Новосибирск: СГГА, 2016. - 279 с.
  11. Концепции целостности эволюции материального мира / Ю. С. Ларионов, Н. А. Ярославцев, С. М. Приходько, Е. В. Екимов // VI Международный конгресс «Слабые и сверхслабые поля и излучения в биологии и медицине». Санкт-Петербург, 2 июня 2012 г.: сб. научных трудов. - Спб., 2012. - С. 268-269.
  12. Ларионов Ю. С. Основы эволюционной теории (Концепции естествознания и аксиомы современной биологии в свете эволюции материи): учеб. пособие. - Омск, изд. ИП Скорнякова Е. В., 2012. - 233 с.
  13. Ларионов Ю. С., Ярославцев Н. А. Зависимость скорости роста растительных тест- объектов семян пшеницы от действия электромагнитных излучений низкой интенсивности естественного происхождения // Вестник СГГА. - 2012. - Вып. 4 (20). - С. 100-106.
  14. Моисеев Н. Н. Расставание с простотой. - М.: АГРАФ, 2012. - С. 98.
  15. Першин С. М. Слабое когерентное излучение ОН и орто-Н2О мазеров как несущая в биокоммуникации: орто-Н2О, как резонансный сенсор // Человек и электромагнитные поля: сб. докладов III Международной конференции. - Саров: РФЯЦ-ВНИИЭФ, 2016. - С. 4- 12.
  16. Петров Н. В. Живой Космос. - СПб.: ООО «Береста», 2015. - 420 с.
  17. Сборник научных трудов VI Международного конгресса «Слабые и сверхслабые поля и излучения в биологии и медицине». - СПб., 2012. - 309 с.
  18. Семенков О. И. Информация. Новейший философский словарь / Сост. и гл. науч. ред. А. А. Грицанов. 3-е изд., испр. - Минск: Книжный дом, 2013. - С. 431-434.
  19. Чернавский Д. С. Синергетика и информация (динамическая теория информации). Изд. 2-е. - М.: Едиториал УРСС, 2014. - 288 с.
  20. Электромагнитный информационный подход к целостной естественнонаучной картине материального мира / Ю. С. Ларионов, В. С. Ларионов, Н. А. Ярославцев, Н. М. При- ходько, Е. И. Баранова // Вестник СГГА. - 2014. - Вып. 4 (28). - С. 158-174.
  21. Энергоинформационные взаимодействия как основа понимания целостной картины мира / Н. А. Ярославцев, Ю. С. Ларионов, С. М. Приходько, Е. В. Екимов // VI Международный конгресс «Слабые и сверхслабые поля и излучения в биологии и медицине». Санкт- Петербург, 2-6 июля 2012 г.: сб. научных трудов. - СПб., 2012. - С. 280-281.
  22. Systems and software engineering - Vocabulary: Although information will necessarily have a representation form to make it communicable, it is the interpretation of this representation (the meaning) that is relevant in the first place [Электронный ресурс]. - Доступ из: https://www/ISO org/obp/ui/#ISO:std: ISO/IEC/IEEE 24765:2010.
  1. Свободные области памяти, разбросанные между используемыми значениями, порождают техническую проблему, решение которой часто называют «сборкой мусора» (garbage collection); во многих языках такая процедура реали­зована.

  2. В современных версиях Delphi строки реализованы динамически, поэтому там приведенное далее описание к типу STRING неприменимо; для совместимости с прежними версиями Паскаля предусмотрен тип SHORTSTRING, сов­падающий с классическим.

  3. Точно такой же механизм используется во всех операционных системах семейства Unix, где файл может принад­лежать нескольким каталогам одновременно.

  4. Такого рода ошибки уже встречались в практике программирования на языке BASIC, где тоже не обязательно объявлять переменные.