Speak.Me Учить иностранные слова

C#: числовые типы (Numeric Types)

ТипSYSTEM псевдонимСуффиксРазмерДиапазон
Целые числа со знаком (Signed integer)
sbyteSByte8 bits–27 до 27–1
shortInt1616 bits–215 до 215–1
intInt3232 bits–231 до 231–1
longInt64L64 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 DecimalM 128 bits ± (~10–28 до 1028)

Среди целочисленных (integral) типов int и long используются наиболее часто. Остальные применяются для функциональной совместимости или когда действительно необходимы большие числа. Из реальных чисел, float и double, также называемые числами с плавающей точкой (floatingpoint types), обычно используются для научных вычислений. Тип decimal обычно используется в финансовых вычислениях, где необходима десятичная арифметика и высокая точность. Различия между double и decimal приведены в следующей таблице:

doubledecimal
Внутреннее представлениедвоичноедесятичное
Точность15-16-значные цифровые данные28-29-значные цифровые данные
Диапазон±(~10–324 до ~10308)±(~10–28 to ~1028)
Специальные значения+0, –0, +∞, –∞, NaNНет
Скорость вычисленияЗависит от процессораНе зависит от процессора и приблизительно в 10 раз медленнее чем double

В связи с тем что типы float и double в своем внутреннем представлении являются двоичными, литералы с дробной частью (десятичные) не являются совсем точными:

По этой причине float и  double лучше не использовать для финансовых вычислений, для которых лучше подходит тип decimal, десятичный в своей основе и поэтому более точный для дробных десятичных чисел.

Числовые литералы (Numeric Literals)

Целочисленные литералы (Integral literals)  могут использовать десятичную (decimal) или шестнадцатеричную (hexadecimal) запись; шестнадцатеричная обозначается префиксом 0x (например, 0x7f = 127).  Реально-числовые литералы также используют десятичную и шестнадцатеричную запись (например, 1E06).

По умолчанию, компилятор определяет тип числовых литералов по следующим критериям: если литерал содержит десятичную точку или знак экспоненты (E) — это double, в противном случае — это int, uint, long, или ulong.

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

Необходимость в суффиксах U и L возникает крайне редко, т.к. почти всегда типы uintlong, и ulong могут быть либо выведены либо неявно преобразованы из int:

Суффикс D технически излишен, т.к. все литералы с десятичной точкой приводятся к double. Суффиксы F и M более полезны: они необходимы при написании дробных литералов типа float или decimal. Без суффикса подобные литералы будут считаться типом double, который не преобразуется скрыто к float или decimal.

Преобразование чисел

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

Преобразование реальных чисел. Число типа float может быть скрыто преобразовано к double, поскольку double способно вместить все возможные значения float. Обратное преобразование должно быть явным. Преобразование между decimal и другими реальными типами должно быть явным.

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

Числовые операторы

Арифметические операторы

Арифметические операторы: + - * / %. Они применимы ко всем числовым типам, корме 8- и 16-битных целочисленных типов.

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

Оператор % возвращает остаток после деления.

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

Операторы инкремента ++ (Incremantal) и декремента — (Decremental) увеличивают и уменьшают (соответственно) числа на 1. Они могут идти до или после переменной, в зависимости от того, когда необходимо изменить переменную: до или после вычисления выражения:

Переполнение и оператор check

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

Оператор checked заставляет генерировать ошибку при переполнении (OverflowException). Он воздействует на выражения с операторами ++, —, — (унарный, обозначающий отрицательное число), +, -, *, / и операторами явного приведения между целочисленными типами. Применять его можно либо к одному выражению, либо к блоку:

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

Побитовые (поразрядные, bitwise) операторы

Каждый целочисленный тип может быть представлен в виде последовательности бит:

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

К побитовым операторам относятся:

  • И — & — устанавливает (в значение 1) только те биты, которые установлены (имеют значение 1) в обоих операндах, остальные биты выключаются (устанавливаются в 0)
  • ИЛИ — | — устанавливает те биты которые установлены либо в одном, либо в другом операнде
  • ИСКЛЮЧАЮЩЕЕ ИЛИ — ^ — устанавливает только те биты, которые установлены либо в одном, либо в другом операнде, но не в обоих одновременно
  • ОТРИЦАНИЕ — ~ — унарный оператор: устанавливает те биты, которые не установлены в операнде
  • СДВИГ ВЛЕВО — << — сдвигает биты левого операнда влево на число позиций, равное второму операнду
  • СДВИГ ВПРАВО — >> — сдвигает биты левого операнда вправо на число позиций, равное второму операнду
Для положительных чисел битовый сдвиг числа вправо на n равносилен целочисленному делению на 2n.  Битовый сдвиг влево на n бит равносилен (для положительных чисел) умножению на 2n.

Операции с 8-битные и 16-битные целыми числами

8-битные и 16-битные целые числа (byte, sbyte, short, ushort) не имеют собственных операторов, поэтому C# неявно преобразовывает их в большие типы при необходимости. В связи с этим при компиляции может возникнуть ошибка, если результату попытаться снова назначить младший тип:

В этом примере x и y скрыто преобразуются в int, чтоб над ними можно было выполнить сложение. Результат в связи с этим тоже будет иметь тип int, который не может быть скрыто преобразован обратно в short (т.к. это может привести к потере данных). Чтобы избежать ошибки, необходимо использовать явное приведение к типу:

Операции над числами с плавающей точкой

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

  • NaN (Not a Number)
  • +∞
  • –∞
  • –0

Деление ненулевого значения на ноль дает бесконечность:

Деление ноль на ноль и вычитание бесконечности из бесконечности дает NaN:

При использовании оператора сравнения ==, значение NaN никогда не будет равно никакому другому значению, в том числе другому значению NaN. Для проверки значения на равенство NaN нужно использовать методы float.IsNaN и double.IsNaN:

Однако, при использовании метода object.Equals два 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, определяющий как строка читается при преобразовании в числовой тип (они позволяют указывать такие аспекты, как могут ли встречаться во входной строке круглые скобки или символ валюты):

Комбинируемые члены NumberStyles:

  • AllowLeadingWhite — допускает наличие в начале входной строки пробелов
  • AllowTrailingWhite — допускает наличие в конце входной строки пробелов
  • AllowLeadingSign — допускает наличие в начале входной строки символов
  • AllowTrailingSign — допускает наличие в конце входной строки символов
  • AllowParentheses — допускает наличие во входной строке скобок
  • AllowDecimalPoint — допускает наличие во входной строке десятичной точки
  • AllowThousands — допускает наличие во входной строке разделителя разрядов
  • AllowExponent — допускает наличие во входной строке экспоненты
  • AllowCurrencySymbol — допускает наличие во входной строке символа валют
  • AllowHexSpecifier — допускает наличие во входной строке символа шестнадцатиричной записи

Составные члены NumberStyles:

  • None — любые символы кроме цифр в входной строке не допустимы
  • Integer — допустимы символы для целых чисел
  • Float — допустимы символы для чисел с плавающей точкой
  • Number — допустимы символы для любых чисел
  • HexNumber — допустимы символы для шестнадцатиричной записи
  • Currency — допустимы символы для валюты
  • Any — допустимы любые символы

Если входная строка содержит символы отличные от цифр, а NumberStyles не методу не передан, будет сгенерировано исключение.