Как задать объем типа данных в си
Оглавление:
Урок №33. Типы данных с плавающей точкой: float, double и long double
| | Обновл. 19 Апр 2023 | 141008 На этом уроке мы рассмотрим типы данных с плавающей точкой в языке С++, их точность и диапазон. Выясним, что такое экспоненциальная запись и как она используется, а также рассмотрим ошибки округления и дадим определения для nan и inf.
Оглавление: отлично подходят для работы с целыми числами, но есть ведь еще и дробные числа. И тут нам на помощь приходит тип данных с плавающей точкой (или «тип данных с плавающей запятой», англ.
«floating point»). Переменная такого типа может хранить любые действительные дробные значения, например: 4320.0, -3.33 или 0.01226.
Почему точка «плавающая»? Дело в том, что точка/запятая перемещается («плавает») между цифрами, разделяя целую и дробную части значения. Есть три типа данных с плавающей точкой: float, double и long double. Язык C++ определяет только их минимальный размер (как и с целочисленными типами).
Типы данных с плавающей точкой всегда являются signed (т.е.
могут хранить как положительные, так и отрицательные числа).
Категория Тип Минимальный размер Типичный размер Тип данных с плавающей точкой float 4 байта 4 байта double 8 байт 8 байт long double 8 байт 8, 12 или 16 байт Объявление переменных разных типов данных с плавающей точкой: float fValue; double dValue; long double dValue2; 123 floatfValue;doubledValue;longdoubledValue2; Если нужно использовать целое число с переменной типа с плавающей точкой, то тогда после этого числа нужно поставить разделительную точку и нуль. Это позволяет различать переменные целочисленных типов от переменных типов с плавающей запятой: int n(5); // 5 — это целочисленный тип double d(5.0); // 5.0 — это тип данных с плавающей точкой (по умолчанию double) float f(5.0f); // 5.0 — это тип данных с плавающей точкой («f» от «float») 123 intn(5);// 5 — это целочисленный тип doubled(5.0);// 5.0 — это тип данных с плавающей точкой (по умолчанию double)floatf(5.0f);// 5.0 — это тип данных с плавающей точкой («f» от «float») Обратите внимание, литералы типа с плавающей точкой по умолчанию относятся к типу double.
Значение 1.2 — это мантисса (или «значащая часть числа»), а 4 — это экспонент (или «порядок числа»). Результатом этого выражения является значение 12000.
Обычно, в экспоненциальной записи, в целой части находится только одна цифра, все остальные пишутся после разделительной точки (в дробной части).
Рассмотрим массу Земли. В десятичной системе счисления она представлена как 5973600000000000000000000 кг. Согласитесь, очень большое число (даже слишком большое, чтобы поместиться в целочисленную переменную размером 8 байт). Это число даже трудно читать (там 19 или 20 нулей?).
Но используя экспоненциальную запись, массу Земли можно представить, как 5.9736 × 1024кг (что гораздо легче воспринимается, согласитесь).
Еще одним преимуществом экспоненциальной записи является сравнение двух очень больших или очень маленьких чисел — для этого достаточно просто сравнить их экспоненты.
В языке C++ буква е /Е означает, что число 10 нужно возвести в степень, которая следует за этой буквой.
Например, 1.2 × 104 эквивалентно 1.2e4, значение 5.9736 × 1024 еще можно записать как 5.9736e24.
Для чисел меньше единицы экспонент может быть отрицательным.
Например, 5e-2 эквивалентно 5 * 10-2, что, в свою очередь, означает 5 / 102 или 0.05. Масса электрона равна 9.1093822e-31 кг. На практике экспоненциальная запись может использоваться в операциях присваивания следующим образом: double d1(5000.0); double d2(5e3); // другой способ присвоить значение 5000 double d3(0.05); double d4(5e-2); // другой способ присвоить значение 0.05 12345 doubled1(5000.0);doubled2(5e3);// другой способ присвоить значение 5000doubled3(0.05);doubled4(5e-2);// другой способ присвоить значение 0.05 Для конвертации чисел в экспоненциальную запись необходимо следовать процедуре, указанной ниже: Ваш экспонент начинается с нуля.
Переместите разделительную точку (которая разделяет целую и дробную части) влево, чтобы слева от нее осталась только одна ненулевая цифра: каждое перемещение точки влево увеличивает экспонент на 1; каждое перемещение точки вправо уменьшает экспонент на 1. Откиньте все нули перед первой ненулевой цифрой в целой части. Откиньте все конечные нули в правой (дробной) части, только если исходное число является целым (без разделительной точки).
Количество значащих цифр определяет точность самого значения. Чем больше цифр в мантиссе, тем точнее значение. Рассмотрим дробь 1/3. Десятичное представление этого числа — 0.33333333333333… (с тройками до бесконечности).
Бесконечное число требует бесконечной памяти для хранения, а у нас в запасе, как правило, 4 или 8 байт. Переменные типа с плавающей запятой могут хранить только определенное количество значащих цифр, остальные — отбрасываются. Точность определяется количеством значащих цифр, которые представляют число без потери данных.
Когда мы выводим переменные типа с плавающей точкой, то точность объекта , по умолчанию, составляет 6. Т.е. на экране мы увидим только 6 значащих цифр, остальные — потеряются.
Например: #include int main() { float f; f = 9.87654321f; std::cout < f>< std::endl; f="987.654321f;" std::cout>< f>< std::endl; f="987654.321f;" std::cout>< f>< std::endl; f="9876543.21f;" std::cout>< f>< std::endl; f="0.0000987654321f;" std::cout>< f>< std::endl; return 0; }> 1234567891011121314151617 #include intmain(){ floatf; f=9.87654321f; std::cout<>
В зависимости от компилятора, экспонент может быть дополнен нулями. Например, 9.87654e+06 — это то же самое, что и 9.87654e6 (просто с добавленным нулем и знаком +).
Минимальное количество цифр экспонента определяется компилятором (Visual Studio использует 2, другие компиляторы могут использовать 3).
Также мы можем переопределить точность cout, используя функцию std::setprecision(), которая находится в iomanip: #include #include // для std::setprecision() int main() { std::cout < std::setprecision(16); задаем точность в 16 цифр float f="3.33333333333333333333333333333333333333f;" std::cout>< f>< std::endl; double d="3.3333333333333333333333333333333333333;" std::cout>< d>< std::endl; return 0; }> 123456789101112 #include #include // для std::setprecision() intmain(){ std::cout
Но, как вы можете видеть, исходные числа имеют больше цифр!
Точность зависит от (в типе float точность меньше, чем в типе double) и от присваиваемого значения: точность float: от 6 до 9 цифр (в основном 7); точность double: от 15 до 18 цифр (в основном 16); точность long double: 15, 18 или 33 цифры (в зависимости от того, сколько байт занимает тип данных на компьютере). Этот принцип относится не только к дробным числам, но и ко всем значениям, которые имеют слишком большое количество значащих цифр. Например: #include #include // для std::setprecision() int main() { float f(123456789.0f); // переменная f имеет 10 значащих цифр std::cout < std::setprecision(9); задаем точность в 9 цифр std::cout>< f>< std::endl; return 0; }> 12345678910 #include #include // для std::setprecision()intmain(){ floatf(123456789.0f);// переменная f имеет 10 значащих цифр std::cout
Значение 123456789.0 имеет 10 значащих цифр, но точность float равна 7. Поэтому мы и получили другое число, произошла потеря данных!
Следовательно, нужно быть осторожными, когда вы используете переменные типа с плавающей точкой вместе с очень большими/очень маленькими числами, которые требуют большей точности, чем их текущий тип данных может предложить.
Диапазон и точность типов данных с плавающей точкой, согласно : Размер Диапазон Точность 4 байта от ±1.18 x 10-38 до ±3.4 x 1038 6-9 значащих цифр (в основном 7) 8 байт от ±2.23 x 10-308 до ±1.80 x 10308 15-18 значащих цифр (в основном 16) 80 бит (12 байт) от ±3.36 x 10-4932 до ±1.18 x 104932 18-21 значащих цифр 16 байт от ±3.36 x 10-4932 до ±1.18 x 104932 33-36 значащих цифр Может показаться немного странным, что 12-байтовая переменная типа с плавающей точкой имеет тот же диапазон, что и 16-байтовая переменная. Это потому, что они имеют одинаковое количество бит, выделенных для экспонента (только в 16-байтовой переменной точность будет выше). Правило: Используйте по умолчанию тип double вместо типа float, так как его точность выше.
Рассмотрим дробь 1/10. В десятичной системе счисления эту дробь можно представить, как 0.1. В двоичной системе счисления эта дробь представлена в виде бесконечной последовательности — 0.00011001100110011… Именно из-за подобных разногласий в представлении чисел в разных системах счисления, у нас могут возникать проблемы с точностью.
Например: #include #include // для std::setprecision() int main() { double d(0.1); std::cout < d>< std::endl; используем точность cout по умолчанию (6 цифр) std::cout>< std::setprecision(17); std::cout>< d>< std::endl; return 0; }> 1234567891011 #include #include // для std::setprecision()intmain(){ doubled(0.1); std::cout<>
После того, как мы изменили для объекта cout точность вывода до 17 цифр, мы увидели, что значением переменной d является не совсем 0.1! Подобное происходит из-за ограничений в количестве выделяемой памяти для переменных типа double, а также из-за необходимости «округлять» числа. По факту мы получили типичную ошибку округления.
Подобные ошибки могут иметь неожиданные последствия: #include #include // для std::setprecision() int main() { std::cout < std::setprecision(17); double d1(1.0); std::cout>< d1>< std::endl; double d2(0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1 + 0.1); должно получиться 1.0 std::cout>< d2>< std::endl; }> 12345678910111213 #include #include // для std::setprecision()intmain(){ std::cout
А что, если бы нам довелось сравнивать эти переменные и, исходя из результата, выполнять определенный сценарий? В таком случае ошибок нам не миновать.
Математические операции (например, сложение или умножение), как правило, только увеличивают масштаб этих ошибок. Даже если 0.1 имеет погрешность в 17-й значащей цифре, то при выполнении операции сложения десять раз, ошибка округления переместится к 16-й значащей цифре. Есть две специальные категории чисел типа с плавающей запятой: inf (или «бесконечность», от англ «infinity»), которая может быть либо положительной, либо отрицательной.
nan (или «не число», от англ «not a number»). Их есть несколько видов (обсуждать все виды здесь мы не будем).
Рассмотрим примеры на практике: #include int main() { double zero = 0.0; double posinf = 5.0 / zero; // положительная бесконечность std::cout < posinf>< "\n"; double neginf="-5.0" zero; отрицательная бесконечность std::cout>< neginf>< "\n"; double nan="zero" zero; не число (математически некорректно) std::cout>< nan>< "\n"; return 0; }> 12345678910111213141516 #include intmain(){ doublezero=0.0; doubleposinf=5.0/zero;// положительная бесконечность std::cout<><"\n"; doubleneginf="-5.0/zero;//" отрицательная бесконечность>"\n";><><"\n"; doublenan="zero/zero;//" не число (математически некорректно)>"\n";><><"\n";>"\n";> Результат выполнения программы: inf -inf -nan(ind) inf означает «бесконечность», а ind означает «неопределенный» (от англ.
«indeterminate»). Обратите внимание, результаты вывода inf и nan зависят от компилятора/архитектуры компьютера, поэтому ваш результат выполнения вышеприведенной программы может отличаться от моего результата. Переменные типа с плавающей точкой отлично подходят для хранения очень больших или очень маленьких (в том числе и дробных) чисел до тех пор, пока они имеют ограниченное количество значащих цифр (не превышают точность определенного типа данных). Переменные типа с плавающей точкой могут иметь небольшие ошибки округления, даже если точность типа не превышена.
В большинстве случаев такие ошибки остаются незамеченными, так как они не столь значительны.
4.000e-3 (4 значащие цифры). 1.23005e2 (6 значащих цифр). 1.46e5 (3 значащие цифры). 1.46000001e5 (9 значащих цифр).
8e-10 (1 значащая цифра). Здесь мантисса не 8.0, а 8, поэтому число и имеет только 1 значащую цифру.
3.45000e4 (6 значащих цифр). Здесь конечные нули не игнорируются, так как в исходном числе есть точка, которая разделяет целую и дробную части. Хотя эта точка никак не влияет на само число, она влияет на его точность. Если бы исходное число было указано, как 34500, то ответ равнялся бы 3.45e4.
Оценить статью:

(494 оценок, среднее: 4,86 из 5)

Загрузка. Поделиться в социальных сетях:
Урок №30.
Размер типов данных
| | Обновл. 2 Сен 2020 | 77419 Как мы уже знаем из , память на современных компьютерах, как правило, организована в блоки, которые состоят из байтов, причем каждый блок имеет свой уникальный адрес.
До этого момента, память можно было сравнивать с почтовыми ящиками (с теми, которые находятся в каждом подъезде), куда мы можем поместить информацию и откуда мы её можем извлечь, а имена переменных — это всего лишь номера этих почтовых ящиков. Тем не менее, эта аналогия не совсем подходит к программированию, так как переменные могут занимать больше 1 байта памяти.
Так как мы, как правило, получаем доступ к памяти через имена переменных, а не через адреса памяти, то компилятор может скрывать от нас все детали работы с переменными разных размеров.
Есть несколько причин по которым полезно знать, сколько памяти занимает определенная переменная/тип данных. Во-первых, чем больше она занимает, тем больше информации сможет хранить. Так как каждый бит содержит либо 0, либо 1, то 1 бит может иметь 2 возможных значения.
2 бита могут иметь 4 возможных значения: бит 0 бит 1 0 0 0 1 1 0 1 1 3 бита могут иметь 8 возможных значений: бит 0 бит 1 бит 2 0 0 0 0 0 1 0 1 0 0 1 1 1 0 0 1 0 1 1 1 0 1 1 1 По сути, переменная с n-ным количеством бит может иметь 2n возможных значений.
Поскольку байт состоит из 8 бит, то он может иметь 28 (256) возможных значений.
Размер переменной накладывает ограничения на количество информации, которую она может хранить. Следовательно, переменные, которые используют больше байт, могут хранить более широкий диапазон значений.
Во-вторых, компьютеры имеют ограниченное количество свободной памяти. Каждый раз, когда мы объявляем переменную, небольшая часть этой свободной памяти выделяется до тех пор, пока переменная существует.
Поскольку современные компьютеры имеют много памяти, то в большинстве случаев это не является проблемой, особенно когда в программе всего лишь несколько переменных. Тем не менее, для программ с большим количеством переменных (например, 100 000), разница между использованием 1-байтовых или 8-байтовых переменных может быть значительной. Возникает вопрос:
«Сколько памяти занимают переменные разных типов данных?»
.
Вы можете удивиться, но размер переменной с любым типом данных зависит от компилятора и/или архитектуры компьютера! Язык C++ гарантирует только их минимальный размер: Категория Тип Минимальный размер Логический тип данных bool 1 байт Символьный тип данных char 1 байт wchar_t 1 байт char16_t 2 байта char32_t 4 байта Целочисленный тип данных short 2 байта int 2 байта long 4 байта long long 8 байт Тип данных с плавающей запятой float 4 байта double 8 байт long double 8 байт Фактический размер переменных может отличаться на разных компьютерах, поэтому для его определения используют оператор sizeof.
Оператор sizeof — это унарный оператор, который вычисляет и возвращает размер определенной переменной или определенного типа данных в байтах. Вы можете скомпилировать и запустить следующую программу, чтобы выяснить, сколько занимают разные типы данных на вашем компьютере: #include int main() { std::cout < "bool:\t\t">< sizeof(bool)>< " bytes">< std::endl; std::cout>< "char:\t\t">< sizeof(char)>< " bytes">< std::endl; std::cout>< "wchar_t:\t">< sizeof(wchar_t)>< " bytes">< std::endl; std::cout>< "char16_t:\t">< sizeof(char16_t)>< " bytes">< std::endl; std::cout>< "char32_t:\t">< sizeof(char32_t)>< " bytes">< std::endl; std::cout>< "short:\t\t">< sizeof(short)>< " bytes">< std::endl; std::cout>< "int:\t\t">< sizeof(int)>< " bytes">< std::endl; std::cout>< "long:\t\t">< sizeof(long)>< " bytes">< std::endl; std::cout>< "long long:\t">< sizeof(long long)>< " bytes">< std::endl; std::cout>< "float:\t\t">< sizeof(float)>< " bytes">< std::endl; std::cout>< "double:\t\t">< sizeof(double)>< " bytes">< std::endl; std::cout>< "long double:\t">< sizeof(long double)>< " bytes">< std::endl; return 0; }> 123456789101112131415161718 #include intmain(){ std::cout<><><">">
Если вам интересно, что значит \t в коде, приведенном выше, то это специальный символ, который используется вместо клавиши TAB.
Мы его использовали для выравнивания столбцов.
Оценить статью:


(522 оценок, среднее: 4,93 из 5)

Загрузка.
Поделиться в социальных сетях:
Типы данных
Содержание Типом данных в программировании называют совокупность двух множеств: множество значений и множество операций, которые можно применять к ним.
Например, к типу данных целых неотрицательных чисел, состоящего из конечного множества натуральных чисел, можно применить операции сложения (+), умножения (*), целочисленного деления (/), нахождения остатка (%) и вычитания (−). Язык программирования, как правило, имеет набор примитивных типов данных — типы, предоставляемые языком программирования как базовая встроенная единица. В C++ такие типы создатель языка называет фундаментальными типами.
Фундаментальными типами в C++ считаются:
- целый (напр., int);
- void.
- с плавающей точкой (напр., float);
- символьный (напр., char);
- перечисления (определяется программистом);
- логический (bool);
Поверх перечисленных строятся следующие типы:
- указательные (напр., int*);
- массивы (напр., char[]);
- другие структуры.
- ссылочные (напр., double&);
Перейдём к понятию литерала (напр., 1, 2.4F, 25e-4, ‘a’ и др.): литерал — запись в исходном коде программы, представляющаясобой фиксированное значение. Другими словами, литерал — это просто отображение объекта (значение) какого-либо типа в коде программы. В C++ есть возможность записи целочисленных значений, значений с плавающей точкой, символьных, булевых, строковых.
Литерал целого типа можно записать в:
- 10-й системе счисления. Например, 1205;
- 16-й системе счисления в формате 0x + число. Например, 0x2F.
- 8-й системе счисления в формате 0 + число. Например, 0142;
24, 030, 0x18 — это всё записи одного и того же числа в разных системах счисления. Для записи чисел с плавающей точкой используют запись через точку: 0.1, .5, 4. — либо в экспоненциальной записи — 25e-100.
Пробелов в такой записи быть не должно. Имя, с которым мы можем связать записанные литералами значения, называют переменной.
Переменная — это поименованная либо адресуемая иным способом область памяти, адрес которой можно использовать для доступа к данным. Эти данные записываются, переписываются и стираются в памяти определённым образом во время выполнения программы.
Переменная позволяет в любой момент времени получить доступ к данным и при необходимости изменить их.
Данные, которые можно получить по имени переменной, называют значением переменной. Для того, чтобы использовать в программе переменную, её обязательно нужно объявить, а при необходимости можно определить (= инициализировать). Объявление переменной в тексте программы обязательно содержит 2 части: базовый тип и декларатор.
Спецификатор и инициализатор являются необязательными частями: const int example = 3; / здесь const — спецификатор / int — базовый тип / example — имя переменной / = 3 — инициализатор.
Имя переменной является последовательностью символов из букв латинского алфавита (строчных и прописных), цифр и/или знака подчёркивания, однако первый символ цифрой быть не может. Имя переменной следует выбирать таким, чтобы всегда было легко догадаться о том, что она хранит, например, «monthPayment».
В конспекте и на практиках мы будем использовать для правил записи переменных нотацию CamelCase. Имя переменной не может совпадать с зарезервированными в языке словами, примеры таких слов: if, while, function, goto, switch и др. Декларатор кроме имени переменной может содержать дополнительные символы:
- [] — массив; после имени;
- & — ссылка; перед именем;
- * — указатель; перед именем;
- *const — константный указатель; перед именем;
- () — функция; после имени.
Инициализатор позволяет определить для переменной её значение сразу после объявления.
Инициализатор начинается с литерала равенства (=) и далее происходит процесс задания значения переменной.
Вообще говоря, знак равенства в C++ обозначает операцию присваивания; с её помощью можно задавать и изменять значение переменной. Для разных типов он может быть разным. Спецификатор задаёт дополнительные атрибуты, отличные от типа.
Приведённый в примере спецификатор const позволяет запретить последующее изменение значение переменной.
Такие неизменяемые переменные называют константными или константой. Объявить константу без инициализации не получится по логичным причинам: const int EMPTY_CONST; // ошибка, не инициализована константная переменная const int EXAMPLE = 2; // константа со значением 2 EXAMPLE = 3; // ошибка, попытка присвоить значение константной переменной Для именования констант принято использовать только прописные буквы, разделяя слова символом нижнего подчёркивания.
Разбирая каждый тип, читатель не должен забывать об определении типа данных. Из названия легко понять, что множество значений состоит из целых чисел. Также множество значений каждого из перечисленных типов может быть знаковым (signed) или беззнаковым (unsigned).
Количество элементов, содержащееся в множестве, зависит от размера памяти, которая используется для хранения значения этого типа. Например, для переменной типа char отводится 1 байт памяти, поэтому всего элементов будет:
- 28N = 28 * 1 = 256, где N — размер памяти в байтах для хранения значения
В таком случае диапазоны доступных целых чисел следующие:
- [-128.127] — для знакового char
- [0.255] — для беззнакового char
По умолчанию переменная целого типа считается знаковой.
Чтобы указать в коде, что переменная должна быть беззнаковой, к базовому типу слева приписывают признак знаковости, т.е. unsigned: unsigned long values; // задаёт целый (длинный) беззнаковый тип. Перечисленные типы отличаются только размерами памяти, которая требуется для хранения.
Поскольку язык C++ достаточно машинно-зависимый стандарт языка лишь гарантирует выполнение следующего условия:
- 1 = размер char ≤ размер short ≤ размер int ≤ размер long.
Обычно размеры типов следующие: char — 1, short — 2, int — 4, long —8, long long — 8 байт. Со значениями целого типа можно совершать арифметические операции: +, -, *, /, %; операции сравнения: ==, !=, <=,>=,><,>, >=; битовые операции: &, |, xor, <,>>.
Большинство операций, таких как сложение, умножение, вычитание и операции сравнения, не вызывают проблем в понимании.
Иногда, после выполнения арифметических операций, результат может оказаться за пределами диапазона значений; в этом случае программа выдаст ошибку. Целочисленное деление (/) находит целую часть от деления одного целого числа, на другое. Например:
- 6 / 4 = 1;
- 8 / 2 = 4.
- 2 / 5 = 0;
Символ процента (%) обозначает операцию определение остатка от деления двух целых чисел:
- 6 % 4 = 2;
- 10 % 3 = 1.
Более сложные для понимания операции — битовые: & (И), | (ИЛИ), xor (исключающее ИЛИ), < (побитовый сдвиг влево),>> (побитовый сдвиг вправо).
Битовые операции И, ИЛИ и XOR к каждому биту информации применяют соответствующую логическую операцию:
- 110 & 310 = 012 & 112 = 012
- 110 = 012
- 310 = 112
- 110 | 310 = 012 | 112 = 112
- 110 xor 310 = 012 xor 112 = 102
В обработке изображения используют 3 канала для цвета: красный, синий и зелёный — плюс прозрачность, которые хранятся в переменной типа int, т.к. каждый канал имеет диапазон значений от 0 до 255.
В 16-иричной системе счисления некоторое значение записывается следующим образом: 0x180013FF; тогда значение 1816 соответствует красному каналу, 0016 — синему, 1316 — зелёному, FF — альфа-каналу (прозрачности).
Чтобы выделить из такого целого числа определённый канал используют т.н. маску, где на интересующих нас позициях стоят F16 или 12.
Т.е., чтобы выделить значение синего канала необходимо использовать маску, т.е.
побитовое И: int blue_channel = 0x180013FF & 0x00FF0000; После чего полученное значение сдвигается вправо на необходимое число бит.
Побитовый сдвиг смещает влево или вправо на столько двоичных разрядов числа, сколько указано в правой части операции. Например, число 39 для типа char в двоичном виде записывается в следующем виде: 00100111.
Тогда: char binaryExample = 39; // 00100111 char result = binaryExample < 2; сдвигаем 2 бита влево, результат: 10011100>Если переменная беззнакового типа, тогда результатом будет число 156, для знакового оно равно -100. Отметим, что для знаковых целых типов единица в старшем разряде битового представления — признак отрицательности числа. При этом значение, в двоичном виде состоящие из всех единиц соответствует -1; если же 1 только в старшем разряде, а в остальных разрядах — нули, тогда такое число имеет минимальное для конкретного типа значения: для char это -128.
Множество значений типа с плавающей точкой является подмножеством вещественных чисел, но не каждое вещественное число представимо в двоичном виде, что приводит иногда к глупым ошибкам: float value = 0.2; value == 0.2; // ошибка, value здесь не будет равно 0.2. Работая с переменными с плавающей точкой, программист не должен использовать операцию проверки на равенство или неравенство, вместо этого обычно используют проверку на попадание в определённый интервал: value — 0.2 < 1e-6; ok, подбирать интервал тоже нужно осторожно>Помимо операций сравнения тип с плавающей точкой поддерживает 4 арифметические операции, которые полностью соответствуют математическим операциям с вещественными числами.
Состоит всего из двух значений: true (правда) и false (ложь). Для работы с переменными данного типа используют логические операции: !
(НЕ), == (равенство), != (неравенство), && (логическое И), || (логическое ИЛИ). Результат каждой операции можно найти в соответствующей таблицы истинности.
например: X Y XOR 0 0 0 0 1 1 1 0 1 1 1 0 Тип char — не только целый тип (обычно, такой тип называют byte), но и символьный, хранящий номер символа из таблицы символом ASCII. Например код 0x41 соответствует символу ‘A’, а 0x71 — ‘t’.
Иногда возникает необходимость использования символов, которые не закреплены в таблицы ASCII и поэтому требует для хранения более 1-го байта. Для них существует широкий символ (wchar_t). Массивы позволяют хранить последовательный набор однотипных элементов.
Массив хранится в памяти непрерывным блоком, поэтому нельзя объявить массив, не указав его размер.
Чтобы объявить массив после имени переменной пишут квадратные скобки ([]) с указанием его размера. Например: int myArray[5]; // Массив из 5-и элементов целого типа Для инициализации массива значения перечисляют в фигурных скобках. Инициализировать таким образом можно только во время объявления переменной.
Кстати, в этом случае необязательно указывать размер массива: int odds[] = {1, 3, 7, 9, 11}; // Массив инициализируется 5-ю значениями Для доступа к определённому значению в массиве (элемента массива) используют операцию доступа по индексу ([]) с указанием номера элемента (номера начинаются с 0). Например: odds[0]; // доступ к первому элементу массива.
Вернёт значение 1 odds[2]; // доступ к третьему элементу.
Вернёт значение 7 odds[4] = 13; // 5-му элементу массива присваиваем новое значение odds[5]; // ошибка доступа Для записи строки программисты используют идею, что строка — последовательный ряд (массив) символов.
Для идентификации конца строки используют специальный символ конца строки: ‘\0’. Такие специальные символы, состоящие из обратного слэша и идентифицирующего символа, называют управляющими или escape-символами. Ещё существуют, например, ‘\n’ — начало новой строки, ‘\t’ — табуляция.
Для записи в строке обратного слэша применяют экранирование — перед самим знаком ставят ещё один слэш: ‘\’. Экранирование также применяют для записи кавычек. Создадим переменную строки: char textExample[5] = {‘T’, ‘e’, ‘s’, ‘t’, ‘\0’}; // записана строка «Test» Существует упрощённая запись инициализации строки: char textExample[5] = “Test”; // Последний символ не пишется, но размер всё ещё 5 Не вдаваясь в подробности, приведём ещё один полезный тип данных — string.
Строки такого типа можно, например, складывать: string hello = «Привет, «; string name = «Макс!»; string hello_name = hello + name; // Получится строка «Привет, Макс!» Ссылка — объект, указывающий на какие-либо данные, но не хранящий их. Например: int a = 2; // переменная «a» указывает на значение 2 int &b = a; // переменная «b» указывает туда же, куда и «a» b = 4; // меняя значение b, программист меняет значение a.
Теперь a = 4 int &c = 4; // ошибка, так делать нельзя, т.к. ссылка нельзя присвоить значение Ссылка является весьма удобным средством для оптимизации выполнения программы, в чём читатель убедится, когда разговор зайдёт о функциях и передачи значений параметров в функции. Чтобы разобраться с этим типом данных, необходимо запомнить, что множество значений этого типа — адреса ячеек памяти, откуда начинаются данные.
Также указатель поддерживает операции сложения (+), вычитания (-) и разыменовывания (*).
Адреса 0x0 означает, что указатель пуст, т.е. не указывает ни на какие данные.
Этот адрес имеет свой литерал — NULL: int *nullPtr = NULL; // пустой указатель Сложение и вычитание адреса с целым числом или другим адресом позволяет передвигаться по памяти, доступной программе. Операция получения данных, начинающихся по адресу, хранящемуся в указателе, называется разыменовывания (*). Программа считывает необходимое количество ячеек памяти и возвращает значение, хранимое в памяти.
int valueInMemory = 2; // задаём переменну целого типа int *somePtr = &valueIntMemory; // копируем адрес переменной, здесь & — возвращает адрес переменной somePtr; // адрес ячейки памяти, например, 0x2F *somePtr; // значение хранится в 4-х ячейках: 0x2F, 0x30, 0x31 и 0x32 Для указателей не доступна операция присваивания, которая синтаксически совпадает с операцией копирования. Другими словами, можно скопировать адрес другого указателя или адрес переменной, но определить значение адреса самому нельзя. Сам указатель хранится в памяти, как и значения переменных других типов, и занимает 4 байта, поэтому можно создать указатель на указатель.
Перечисления единственный базовый тип, задаваемый программистом.
По большому счёту перечисление — упорядоченный набор именованных целочисленных констант, при этом имя перечисления будет базовым типом. enum color {RED, BLUE, GREEN}; По умолчанию, RED = 0, BLUE = 1, GREEN = 2. Поэтому значения можно сравнивать между собой, т.е.
RED < blue>< green. программист при объявлении перечисления может самостоятельно задать значения каждой из> enum access {READ = 1, WRITE = 2, EXEC = 4}; Часто удобно использовать перечисления, значения которых являются степенью двойки, т.к.
в двоичном представлении число, являющееся степенью 2-и, будет состоять из 1-й единицы и нулей.
Например: 810 = 000010002 Результат сложения этих чисел между собой всегда однозначно указывает на то, какие числа складывались: 3710 = 001001012 = 000000012 + 000001002 + 001000002 = 110 + 410 + 3210 Синтаксически тип void относится к фундаментальным типам, но использовать его можно лишь как часть более сложных типов, т.к.
объектов типа void не существует. Как правило, этот тип используется для информирования о том, что у функции нет возвращаемого значения либо в качестве базового типа указателя на объекты неопределённых типов: void object; // ошибка, не существует объектов типа void void &reference; // ошибка, не существует ссылов на void void *ptr; // ok, храним указатель на неизвестный тип Часто мы будем использовать void именно для обозначения того, что функция не возвращает никакого значения.
С указателем типа void работают, когда программист берёт полностью на себя заботу о целостности памяти и правильном приведении типа. Часто бывает необходимо привести значение переменной одного типа к другому. В случае, когда множество значений исходного типа является подмножеством большего типа (например, int является подмножеством long, а long — double), компилятор способен неявно (implicitly) изменить тип значения.
int integer = 2; float floating = integer; // floating = 2.0 Обратное приведение типа будет выполнено с потерей информации, так от числа с плавающей точкой останется только целая часть, дробная будет потеряна. Существует возможность явного (explicitly) преобразования типов, для этого слева от переменной или какого-либо значения исходного типа в круглых скобках пишут тип, к которому будет произведено приведение: int value = (int) 2.5; Те операции, которые мы выполняли ранее, называют бинарными: слева и справа от символа операции находятся значения или переменные, например, 2 + 3. В языках программирования помимо бинарных операций также используют унарные операции, которые применяются к переменным.
Они могу находится как слева, так и справа от переменной, несколько таких операций встречались ранее — операция разыменовывания (*) и взятие адреса переменной (&) являются унарными.
Операторы «++» и «—» увеличивают и уменьшают значение целочисленной переменной на 1 соответственно, причём могу писаться либо слева, либо справа от переменной. В C++ также применяется сокращённая запись бинарных операций на тот случай, когда в левой и правой частях выражения находится одна и та же переменная, т.е.
,>,>

Оглавление:Оценка автомобиля для наследства 1500 руб.Оценщик...

Оглавление:В ПТС нет места для нового владельцаВ ПТС нет места...

15-я отдельная бригада радиоэлектронной борьбы (в/ч 71615) » Местом...