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

ТипSYSTEM псевдонимСуффиксРазмерДиапазон
Целые числа со знаком (Signed integer)
sbyteSByte 8 bits–27 до 27–1
shortInt16 16 bits–215 до 215–1
intInt32 32 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 Decimal 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) 
Денежное значение1.2, «C»
1.2, «C4»
$1.20
$1.2000
Цифра указывает количество знаков после запятой 
Процент .503, «P»
.503, «P0»
50.30 %
50 %
Цифра указывает количество знаков после запятой 

X или x 

Шестнадцатеричный формат47, «X»
47, «x»
47, «X4»
2F
2f
002F
X — верхний регистр, x — нижний регистр
Округление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 не методу не передан, будет сгенерировано исключение.

Добавить комментарий

Ваш e-mail не будет опубликован. Обязательные поля помечены *