Содержание
| Тип | SYSTEM псевдоним | Суффикс | Размер | Диапазон | 
|---|---|---|---|---|
| Целые числа со знаком (Signed integer) | ||||
| sbyte | SByte | 8 bits | –27 до 27–1 | |
| short | Int16 | 16 bits | –215 до 215–1 | |
| int | Int32 | 32 bits | –231 до 231–1 | |
| long | Int64 | L | 64 bits | –263 до 263–1 | 
| Целые числа бес знака (Unsigned integer) | ||||
| byte | Byte | 8 bits | 0 до 28–1 | |
| ushort | UInt16 | 16 bits | 0 до 216–1 | |
| uint | UInt32 | U | 32 bits | 0 до 232–1 | 
| ulong | UInt64 | UL | 64 bits | 0 до 264–1 | 
| Реальные числа (Real number) | ||||
| float | Single | F | 32 bits | ± (~10–45 до 1038) | 
| double | Double | D | 64 bits | ± (~10–324 до 10308) | 
| decimal | Decimal | M | 128 bits | ± (~10–28 до 1028) | 
Среди целочисленных (integral) типов int и long используются наиболее часто. Остальные применяются для функциональной совместимости или когда действительно необходимы большие числа. Из реальных чисел, float и double, также называемые числами с плавающей точкой (floatingpoint types), обычно используются для научных вычислений. Тип decimal обычно используется в финансовых вычислениях, где необходима десятичная арифметика и высокая точность. Различия между double и decimal приведены в следующей таблице:
| double | decimal | |
|---|---|---|
| Внутреннее представление | двоичное | десятичное | 
| Точность | 15-16-значные цифровые данные | 28-29-значные цифровые данные | 
| Диапазон | ±(~10–324 до ~10308) | ±(~10–28 to ~1028) | 
| Специальные значения | +0, –0, +∞, –∞, NaN | Нет | 
| Скорость вычисления | Зависит от процессора | Не зависит от процессора и приблизительно в 10 раз медленнее чем double | 
В связи с тем что типы float и double в своем внутреннем представлении являются двоичными, литералы с дробной частью (десятичные) не являются совсем точными:
| 1 2 3 | float tenth = 0.1f; // Не совсем 0.1 float one = 1f; Console.WriteLine (one - tenth * 10f); // -1.490116E-08 | 
 По этой причине float и  double лучше не использовать для финансовых вычислений, для которых лучше подходит тип decimal, десятичный в своей основе и поэтому более точный для дробных десятичных чисел.
Числовые литералы (Numeric Literals)
Целочисленные литералы (Integral literals)  могут использовать десятичную (decimal) или шестнадцатеричную (hexadecimal) запись; шестнадцатеричная обозначается префиксом 0x (например, 0x7f = 127).  Реально-числовые литералы также используют десятичную и шестнадцатеричную запись (например, 1E06).
По умолчанию, компилятор определяет тип числовых литералов по следующим критериям: если литерал содержит десятичную точку или знак экспоненты (E) — это double, в противном случае — это int, uint, long, или ulong.
Тип литерала также можно указать с помощью суффиксов, перечисленных в таблице выше. Суффикс ставиться сразу после литерала, например:
| 1 | decimal d = 3.5M; // M = decimal (регистрозависимо) | 
 Необходимость в суффиксах U и L возникает крайне редко, т.к. почти всегда типы uint, long, и ulong могут быть либо выведены либо неявно преобразованы из int:
| 1 | long i = 5; // Скрытое преобразование из int в long | 
 Суффикс D технически излишен, т.к. все литералы с десятичной точкой приводятся к double. Суффиксы F и M более полезны: они необходимы при написании дробных литералов типа float или decimal. Без суффикса подобные литералы будут считаться типом double, который не преобразуется скрыто к float или decimal.
| 1 2 | float f = 4.5F; // Без суффикса не скомпилируется decimal d = -1.23M; // Без суффикса не скомпилируется | 
Преобразование чисел
Скрытое преобразование целых чисел возможно только когда конечный тип вмещает все возможные значения исходного, в противном случае необходимо явное преобразование:
| 1 2 3 | int x = 12345; // int - 32-битное число long y = x; // Скрытое преобразование к 64-битному числу short z = (short)x; // Явное преобразование к 16-битному числу | 
 Преобразование реальных чисел. Число типа float может быть скрыто преобразовано к double, поскольку double способно вместить все возможные значения float. Обратное преобразование должно быть явным. Преобразование между decimal и другими реальными типами должно быть явным.
Преобразование между реальными и целыми числами. Преобразование целых чисел в реальные может быть скрытым, а вот обратное должно быть явным. Преобразование реальных чисел в целые происходит путем отсечения дробной части (без округления). Если необходимо преобразование с округлением, нужно использовать System.Convert класс. Важно помнить, что преобразование больших целых чисел в числа с плавающей точкой сохраняет их величину (magnitude, колличество цифр), но может привести к потере точности (precision):
| 1 2 3 | int i1 = 100000001; float f = i1; // Величина сохранена, точность потеряна int i2 = (int)f; // 100000000 | 
Числовые операторы
Арифметические операторы
Арифметические операторы: + - * / %. Они применимы ко всем числовым типам, корме 8- и 16-битных целочисленных типов.
При делении целых чисел остаток всегда отсекается. При делении на переменную равную нулю возникает ошибка времени исполнения, а при делении на литерал или константу 0 — ошибка времени компиляции.
Оператор % возвращает остаток после деления.
Инкремент и декремент
Операторы инкремента ++ (Incremantal) и декремента — (Decremental) увеличивают и уменьшают (соответственно) числа на 1. Они могут идти до или после переменной, в зависимости от того, когда необходимо изменить переменную: до или после вычисления выражения:
| 1 2 3 4 | int x = 0; Console.WriteLine (x++); // Выведет 0; x = 1 Console.WriteLine (++x); // Выведет 2; x = 2 Console.WriteLine (--x); // Выведет 1; x = 1 | 
Переполнение и оператор check
При выполнении арифметических операций с целыми числами возможно переполнение (Integral overflow) — ситуация, когда полученный результат превышает арифметические пределы типы. Как правило оно происходит тихо: никакие исключения не выбрасываются.
Оператор checked заставляет генерировать ошибку при переполнении (OverflowException). Он воздействует на выражения с операторами ++, —, — (унарный, обозначающий отрицательное число), +, -, *, / и операторами явного приведения между целочисленными типами. Применять его можно либо к одному выражению, либо к блоку:
| 1 2 3 4 5 6 7 | int a = 1000000, b = 1000000; int c = checked (a * b); // Применяется к одному выражению checked // Применяется к блоку выражений { c = a * b; ... } | 
 В последнем случае, если для какого-либо выражения или блока необходимо отключить проверку переполнения, аналогичным способом необходимо использовать оператор unchecked.
Побитовые (поразрядные, bitwise) операторы
Каждый целочисленный тип может быть представлен в виде последовательности бит:
| 1 2 3 4 5 | int a = 0;   // 00000000 int a = 1;   // 00000001 int a = 2;   // 00000010 int a = 10;  // 00001010 int a = 255; // 11111111 | 
Битовые операторы применяются последовательно к каждой паре соответствующих битов своих операндов. Результатом будет значение того же типа, что и операнды, каждый бит которого есть результат применения соответствующего побитового оператора.
К побитовым операторам относятся:
- И — &— устанавливает (в значение 1) только те биты, которые установлены (имеют значение 1) в обоих операндах, остальные биты выключаются (устанавливаются в 0)
- ИЛИ — |— устанавливает те биты которые установлены либо в одном, либо в другом операнде
- ИСКЛЮЧАЮЩЕЕ ИЛИ — ^— устанавливает только те биты, которые установлены либо в одном, либо в другом операнде, но не в обоих одновременно
- ОТРИЦАНИЕ — ~— унарный оператор: устанавливает те биты, которые не установлены в операнде
- СДВИГ ВЛЕВО — <<— сдвигает биты левого операнда влево на число позиций, равное второму операнду
- СДВИГ ВПРАВО — >>— сдвигает биты левого операнда вправо на число позиций, равное второму операнду
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | int a = 5; // 00000101 int b = 6; // 00000110 Console.WriteLine ( a & b ); // 00000100 == 4 Console.WriteLine ( a | b ); // 00000111 == 7 Console.WriteLine ( a ^ b ); // 00000011 == 3 Console.WriteLine ( = ~ a ); // 11111010 == 250 int a = 43; // 00101011 Console.WriteLine ( a >> 1 ); // 00010101 == 21 Console.WriteLine ( a >> 2 ); // 00001010 == 10 Console.WriteLine ( a >> 3 ); // 00000101 == 5 Console.WriteLine ( a >> 5 ); // 00000001 == 1 int a = 5; // 00000101 Console.WriteLine ( a << 1 ); // 00001010 == 10 Console.WriteLine ( a << 2 ); // 00010100 == 20 Console.WriteLine ( 2 << 3 ); // 00101000 == 40 | 
n бит равносилен (для положительных чисел) умножению на 2n.Операции с 8-битные и 16-битные целыми числами
8-битные и 16-битные целые числа (byte, sbyte, short, ushort) не имеют собственных операторов, поэтому C# неявно преобразовывает их в большие типы при необходимости. В связи с этим при компиляции может возникнуть ошибка, если результату попытаться снова назначить младший тип:
| 1 2 | short x = 1, y = 1; short z = x + y; // Ошибка времени компиляции | 
 В этом примере x и y скрыто преобразуются в int, чтоб над ними можно было выполнить сложение. Результат в связи с этим тоже будет иметь тип int, который не может быть скрыто преобразован обратно в short (т.к. это может привести к потере данных). Чтобы избежать ошибки, необходимо использовать явное приведение к типу:
| 1 | short z = (short) (x + y); | 
Операции над числами с плавающей точкой
Типы с плавающей точкой (в отличие от целочисленных) имеют ряд специальных значений, которые ведут себя по особенному в ряде случаев. Этими специальными значениями являются:
- NaN(Not a Number)
- +∞
- –∞
- –0
Деление ненулевого значения на ноль дает бесконечность:
| 1 2 3 4 | Console.WriteLine ( 1.0 / 0.0); // Бесконечность Console.WriteLine (–1.0 / 0.0); // -Бесконечность Console.WriteLine ( 1.0 / –0.0); // -Бесконечность Console.WriteLine (–1.0 / –0.0); // Бесконечность | 
 Деление ноль на ноль и вычитание бесконечности из бесконечности дает NaN:
| 1 2 | Console.Write ( 0.0 / 0.0); // NaN Console.Write ((1.0 / 0.0) – (1.0 / 0.0)); // NaN | 
 При использовании оператора сравнения ==, значение NaN никогда не будет равно никакому другому значению, в том числе другому значению NaN. Для проверки значения на равенство NaN нужно использовать методы float.IsNaN и double.IsNaN:
| 1 2 | Console.WriteLine (0.0 / 0.0 == double.NaN); // False Console.WriteLine (double.IsNaN (0.0 / 0.0)); // True | 
 Однако, при использовании метода object.Equals два NaN значения будут равны:
| 1 | bool isTrue = object.Equals (0.0/0.0, double.NaN); | 
Преобразование чисел в строку, форматные строки
Числовые типы определяют экземплярный метод ToString, позволяющий преобразовать число в строку. В качестве дополнительного параметра метод может принимать форматные строки. Подробно этот метод и форматные строки рассмотрены в разделе, посвященном форматированию и преобразованию строк. Ниже будут перечислены стандартные и специальные форматные строки для чисел.
Стандартные форматные строки для чисел
| Символ | Значение | Пример | Результат | Примечание | 
|---|---|---|---|---|
| G или g | Общий (general) формат | 1.2345, «G» 0.00001, «G» 0.00001, «g» 1.2345, «G3» 12345, «G3» | 1.2345 1E-05 1e-05 1.23 1.23E04 | Перключается на экспоненциальную запись для очень маленьких и больших чисел. Цифра ограничивает точность (количество цифр) | 
| F | Формат с фиксированной точкой | 2345.678, «F2» 2345.6, «F2» | 2345.68 2345.60 | Цифра указывает сколько знаков оставить после запятой | 
| N | Формат с фиксированной точкой и разделителем групп | 2345.678, «N2» 2345.6, «N2» | 2,345.68 2,345.60 | Тоже самое что и F, но с разделением групп (тысяч) | 
| D | Заполнение ведущими нулями | 123, «D5» 123, «D1» | 00123 123 | Только для целых типов. Цифра указывает до какой длины дополнять, усечение не происходит | 
| E или e | Экспоненциальная запись | 56789, «E» 56789, «e» 56789, «E2» | 5.678900E+004 5.678900e+004 5.68E+004 | Цифра указывает точность (по умолчанию — 6) | 
| C | Денежное значение | 1.2, «C» 1.2, «C4» | $1.20 $1.2000 | Цифра указывает количество знаков после запятой | 
| P | Процент | .503, «P» .503, «P0» | 50.30 % 50 % | Цифра указывает количество знаков после запятой | 
| X или x | Шестнадцатеричный формат | 47, «X» 47, «x» 47, «X4» | 2F 2f 002F | X — верхний регистр, x — нижний регистр | 
| R | Округление | 1f / 3f, «R» | 0.333333343 | 
Указание иной форматной строки, пустой строки или null эквивалентно «G».
Специальные форматные строки для чисел
| Символ | Значение | Пример | Результат | Примечание | 
|---|---|---|---|---|
| # | Заполнитель для цифр | 12.345, «.##» 12.345, «.####» | 12.35 12.345 | |
| 0 | Заполнитель для нуля | 12.345, «.00» 12.345, «.0000» 99, «000.00» | 12.35 12.3500 099.00 | |
| . | Десятичная точка | |||
| , | Разделитель групп | 1234, «#,###,###» 1234, «0,000,000» | 1,234 0,001,234 | |
| , | Коэффициент | 1000000, «#,» 1000000, «#,,» | 1000 1 | |
| % | Процентная запись | 0.6, «00%» | 60% | |
| E0, e0, E+0, e+0 E-0, e-0 | Экспоненциальная запись | 1234, «0E0» 1234, «0E+0» 1234, «0.00E00» 1234, «0.00e00» | 1E3 1E+3 1.23E03 1.23e03 | |
| / | Скобка для литерального символа | 50, @»\#0″ | #50 | Используется в сочетании с префиксом @ в строках или можно применять // | 
| ‘xx»xx’ | Скобка для литеральной строки | 50, «0 ‘…'» | 50 … | |
| ; | Разделитель секций | 15, «#;(#);zero» −5, «#;(#);zero» 0, «#;(#);zero» | 15 (5) zero | |
| другой символ | Литерал | 35.2, «$0 . 00c» | $35 . 20c | 
Преобразование строки в число, NumberStyles
Преобразование строки в число можно осуществить с помощью статических методов Parse и TryParse. Подробно эти методы рассмотрены в разделе, посвященном форматированию и преобразованию строк.
Оба метода могут принимать enum NumberStyles, определяющий как строка читается при преобразовании в числовой тип (они позволяют указывать такие аспекты, как могут ли встречаться во входной строке круглые скобки или символ валюты):
| 1 2 3 4 5 | int error = int.Parse ("(2)"); // Генерация исключения int minusTwo = int.Parse ("(2)", NumberStyles.Integer |                                  NumberStyles.AllowParentheses); // OK decimal fivePointTwo = decimal.Parse ("£5.20", NumberStyles.Currency,                        CultureInfo.GetCultureInfo ("en-GB")); | 
 Комбинируемые члены NumberStyles:
- AllowLeadingWhite— допускает наличие в начале входной строки пробелов
- AllowTrailingWhite— допускает наличие в конце входной строки пробелов
- AllowLeadingSign— допускает наличие в начале входной строки символов
- AllowTrailingSign— допускает наличие в конце входной строки символов
- AllowParentheses— допускает наличие во входной строке скобок
- AllowDecimalPoint— допускает наличие во входной строке десятичной точки
- AllowThousands— допускает наличие во входной строке разделителя разрядов
- AllowExponent— допускает наличие во входной строке экспоненты
- AllowCurrencySymbol— допускает наличие во входной строке символа валют
- AllowHexSpecifier— допускает наличие во входной строке символа шестнадцатиричной записи
Составные члены NumberStyles:
- None— любые символы кроме цифр в входной строке не допустимы
- Integer— допустимы символы для целых чисел
- Float— допустимы символы для чисел с плавающей точкой
- Number— допустимы символы для любых чисел
- HexNumber— допустимы символы для шестнадцатиричной записи
- Currency— допустимы символы для валюты
- Any— допустимы любые символы
Если входная строка содержит символы отличные от цифр, а NumberStyles не методу не передан, будет сгенерировано исключение.

