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

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

Содержание

Тип 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 в своем внутреннем представлении являются двоичными, литералы с дробной частью (десятичные) не являются совсем точными:

По этой причине 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 не методу не передан, будет сгенерировано исключение.