Встроенные числовые преобразования (справочник по c#)built-in numeric conversions (c# reference)
Содержание:
- Типы с плавающей точкой
- Полиморфизм
- Характеристики типов с плавающей запятойCharacteristics of the floating-point types
- Изучение порядка операцийExplore order of operations
- Переполнение
- Целочисленные типы данных
- Языки программирования и типы данных
- Символы
- Типы указателей
- Арифметическое переполнение и деление на нульArithmetic overflow and division by zero
- Работа с типом doubleWork with the double type
Типы с плавающей точкой
Числа с плавающей точкой (иногда их называют действительными числами) применяются при вычислении выражений, в которых требуется точность до десятичного знака. Например, это может быть вычисление квадратного корня, значений синуса, косинуса и т.п. Существует два типа с плавающей точкой: float и double, которые представляют числа одинарной и двойной точности.
Слово «плавающая» означает, что десятичная точка может располагаться в любом месте (она «плавает»). Вот коты плавать не особенно любят, поэтому они не float и не double.
Тип float
Тип float определяет значение одинарной точности, которое занимает 32 бит. Переменные данного типа удобны, когда требуется дробная часть без особой точности, например, для денежных сумм.
Рекомендуется добавлять символ F или f для обозначения этого типа, иначе число будет считаться типом double.
Конвертируем из строки.
Класс Float является оболочкой для данного типа. Без необходимости не используйте в Android класс Float.
Также есть специальный класс BigDecimal для проведения арифметических действий повышенной точности (финансовые расчёты).
Тип double
Тип double обеспечивает двойную точность, что видно из его названия (double — двойная). Занимает 64 бит для хранения значений. Многие математические функции возвращают значения типа double. Кстати, современные процессоры оптимизированы под вычисления значений двойной точности, поэтому они предпочтительнее, чем тип float.
Тип double содержит не только числа, но и слова. Сейчас вам докажу. Разделим число типа double на ноль. Ошибки не произойдёт.
Пример вернёт значение Infinity (Бесконечность). Если разделить отрицательное число на ноль, то вернётся -Infinity.
А что произойдёт, если сложить две бесконечности? Если рассуждать логически, то сломается интернет, наступит конец света или можно вызвать Волдеморта. Я долго не решался, но потом набрался храбрости и попробовал.
Вернулось ещё одно слово — NaN. Что это вообще? Может должно вернуться Nyan — ну вы знаете, это странный котик, который летит бесконечно в космосе, оставляя за собой шлейф из радуги.
Умножать две бесконечности я побоялся. И вам не советую.
Класс Double является оболочкой для данного типа. Без необходимости не используйте в Android класс Double.
Конвертация double в строку
При работе с числами double следует держать ухо востро. Рассмотрим пример конвертации трёх чисел.
Первые два числа нормально преобразовались, а вот третье число преобразовалось в строку в странном виде (на самом деле это научное представление числа). И это может источником проблемы при передаче строки куда-нибудь, например, на сервер. Если сервер не ожидает от вас такой подлости, то будет генерировать ошибки из-за странной записи. Нужно найти другие способы конвертации.
Первый способ — используем String.format().
Последний пример самый подходящий для нас, но вам нужно знать, сколько знаков идёт после десятичной точки. Остальные два пригодятся, если число можно округлить.
Второй способ — метод Double.toString(). У меня метод превратил число в «непонятную» строку. А у некоторых этот пример возвращал строку в нормальном виде. Не заслуживает доверия.
Третий способ — добавить пустую строку. В Android не помогло, хотя тоже утверждается, что у кого-то выводится в нормальном виде. Врут, наверное.
Четвёртый экзотический способ, которым редко пользуются — DecimalFormat.
Полиморфизм
полиморфизмом
В итоге
- выделяйте главные характеристики объекта;
- выделяйте общие свойства и поведение и используйте наследование при создании объектов;
- используйте абстрактные типы для описания объектов;
- старайтесь всегда скрывать методы и поля, относящиеся к внутренней реализации класса.
Характеристики типов с плавающей запятойCharacteristics of the floating-point types
C# поддерживает следующие предварительно определенные типы с плавающей запятой:C# supports the following predefined floating-point types:
Ключевое слово или тип C#C# type/keyword | Приблизительный диапазон значенийApproximate range | ТочностьPrecision | РазмерSize | Тип .NET.NET type |
---|---|---|---|---|
От ±1,5 x 10−45 до ±3,4 x 1038±1.5 x 10−45 to ±3.4 x 1038 | 6–9 цифр~6-9 digits | 4 байта4 bytes | System.Single | |
от ±5,0 × 10−324 до ±1,7 × 10308±5.0 × 10−324 to ±1.7 × 10308 | 15–17 цифр~15-17 digits | 8 байт8 bytes | System.Double | |
от ±1,0 x 10-28 до ±7,9228 x 1028±1.0 x 10-28 to ±7.9228 x 1028 | 28-29 знаков28-29 digits | 16 байт16 bytes | System.Decimal |
В приведенной выше таблице каждый тип ключевого слова C# из крайнего левого столбца является псевдонимом для соответствующего типа .NET.In the preceding table, each C# type keyword from the leftmost column is an alias for the corresponding .NET type. Они взаимозаменяемые.They are interchangeable. Например, следующие объявления объявляют переменные одного типа:For example, the following declarations declare variables of the same type:
По умолчанию все типы с плавающей запятой имеют значение .The default value of each floating-point type is zero, . Все типы с плавающей запятой имеют константы и с минимальным и максимальными итоговыми значениями этого типа.Each of the floating-point types has the and constants that provide the minimum and maximum finite value of that type. Типы и также предоставляют константы, обозначающие бесконечные и нечисловые значения.The and types also provide constants that represent not-a-number and infinity values. Например, тип предоставляет следующие константы: Double.NaN, Double.NegativeInfinity и Double.PositiveInfinity.For example, the type provides the following constants: Double.NaN, Double.NegativeInfinity, and Double.PositiveInfinity.
Так как тип характеризуется более высокой точностью и меньшим диапазоном, чем и , он подходит для финансовых расчетов.Because the type has more precision and a smaller range than both and , it’s appropriate for financial and monetary calculations.
В одном и том же выражении можно сочетать и целочисленные типы, и типы и .You can mix integral types and the and types in an expression. В этом случае целочисленные типы неявно преобразуются в один из типов с плавающей запятой. При необходимости тип неявно преобразуется в .In this case, integral types are implicitly converted to one of the floating-point types and, if necessary, the type is implicitly converted to . Выражение вычисляется следующим образом.The expression is evaluated as follows:
- Если в выражении есть тип , оно оценивается как или в реляционных сравнениях или сравнениях на равенство.If there is type in the expression, the expression evaluates to , or to in relational and equality comparisons.
- Если в выражении нет типа , оно оценивается как или в реляционных сравнениях или сравнениях на равенство.If there is no type in the expression, the expression evaluates to , or to in relational and equality comparisons.
Можно также смешивать целочисленные типы и тип в выражении.You can also mix integral types and the type in an expression. В этом случае целочисленные типы неявно преобразуются в тип , а выражение вычисляется как или в реляционных сравнениях и сравнениях на равенство.In this case, integral types are implicitly converted to the type and the expression evaluates to , or to in relational and equality comparisons.
Тип нельзя смешивать с типами и в выражении.You cannot mix the type with the and types in an expression. В этом случае, если требуется выполнить арифметические операции или операции сравнения или равенства, необходимо явно преобразовать операнды из типа или в тип , как показано в следующем примере:In this case, if you want to perform arithmetic, comparison, or equality operations, you must explicitly convert the operands either from or to the type, as the following example shows:
Можно использовать строки стандартных числовых форматов или строки пользовательских числовых форматов для форматирования значения с плавающей запятой.You can use either standard numeric format strings or custom numeric format strings to format a floating-point value.
Изучение порядка операцийExplore order of operations
Закомментируйте вызов .Comment out the call to . Это поможет упорядочить выходные данные в этом разделе.It will make the output less cluttered as you work in this section:
запускает комментарий в C#.The starts a comment in C#. Комментарии — это любой текст, который должен быть сохранен в исходном коде, но не должен выполняться как код.Comments are any text you want to keep in your source code but not execute as code. Компилятор не создает исполняемый код из комментариев.The compiler doesn’t generate any executable code from comments.
Язык C# определяет приоритет математических операций в соответствии с правилами математики.The C# language defines the precedence of different mathematics operations with rules consistent with the rules you learned in mathematics.
Умножение и деление имеют приоритет над сложением и вычитанием.Multiplication and division take precedence over addition and subtraction.
Чтобы удостовериться в этом, добавьте следующий код в метод и выполните команду :Explore that by adding the following code to your method, and executing :
В выходных данных видно, что умножение выполняется раньше сложения.The output demonstrates that the multiplication is performed before the addition.
Можно применить другую последовательность операций. Для этого операции, которые должны выполняться первыми, нужно заключить в скобки.You can force a different order of operation by adding parentheses around the operation or operations you want performed first. Добавьте приведенные ниже строки и выполните код еще раз.Add the following lines and run again:
Поэкспериментируйте, объединяя различные операции.Explore more by combining many different operations. Добавьте в конец метода строки, подобные приведенным ниже.Add something like the following lines at the bottom of your method. Выполните еще раз.Try again.
Возможно, вы заметили интересное поведение целых чисел.You may have noticed an interesting behavior for integers. Деление целых чисел всегда дает результат в виде целого числа, даже если ожидаемый результат содержит десятичную или дробную часть.Integer division always produces an integer result, even when you’d expect the result to include a decimal or fractional portion.
Если вы еще не видели пример такого поведения, добавьте следующий код в конец метода :If you haven’t seen this behavior, try the following code at the end of your method:
Выполните еще раз, чтобы просмотреть результаты.Type again to see the results.
Прежде чем продолжить, давайте поместив весь код, который вы написали в этом разделе, в новый метод.Before moving on, let’s take all the code you’ve written in this section and put it in a new method. Вызовите этот новый метод .Call that new method .
Результат должен быть примерно таким:You should write something like this:
Переполнение
Вопрос: «Что произойдет, если мы попытаемся использовать значение, которое находится вне диапазона значений определенного типа данных?». Ответ: «Переполнение».
Переполнение (англ. «overflow») случается при потере бит из-за того, что переменной не было выделено достаточно памяти для их хранения.
На уроке №28 мы говорили о том, что данные хранятся в бинарном (двоичном) формате и каждый бит может иметь только 2 возможных значения ( или ). Вот как выглядит диапазон чисел от 0 до 15 в десятичной и двоичной системах:
Десятичная система | Двоичная система |
1 | 1 |
2 | 10 |
3 | 11 |
4 | 100 |
5 | 101 |
6 | 110 |
7 | 111 |
8 | 1000 |
9 | 1001 |
10 | 1010 |
11 | 1011 |
12 | 1100 |
13 | 1101 |
14 | 1110 |
15 | 1111 |
Как вы можете видеть, чем больше число, тем больше ему требуется бит. Поскольку наши переменные имеют фиксированный размер, то на них накладываются ограничения на количество данных, которые они могут хранить.
Целочисленные типы данных
Целочисленный тип данных — это тип, переменные которого могут содержать только целые числа (без дробной части, например: -2, -1, 0, 1, 2). В языке C++ есть 5 основных целочисленных типов, доступных для использования:
Категория | Тип | Минимальный размер |
Символьный тип данных | char | 1 байт |
Целочисленный тип данных | short | 2 байта |
int | 2 байта (но чаще всего 4 байта) | |
long | 4 байта | |
long long | 8 байт |
Примечание: Тип char — это особый случай: он является как целочисленным, так и символьным типом данных. Об этом детально мы поговорим на одном из следующих уроков.
Основным различием между целочисленными типами, перечисленными выше, является их размер, чем он больше, тем больше значений сможет хранить переменная этого типа.
Языки программирования и типы данных
В зависимости от принятой системы типов и способов с ней работать различают языки программирования:
- со статической и динамической типизацией;
- с сильной и слабой типизацией;
- с явной и неявной типизацией.
В языках со статической типизацией тип переменной выводится на этапе компиляции и в случае, если эта операция не может быть выполнена, то процесс компиляции не будет завершен. Динамическая типизация предполагает определение типа переменной во время выполнения программы, такой подход чаще всего встречается среди интерпретируемых языков.
Примеры языков со статической типизацией: C#, Java, C, C++, код объявления переменной выглядит так:
double value = 0.123;
Примеры языков с динамической типизацией: Python, PHP. Пример кода на Python
value = 0.123
В языках с сильной типизацией операции над значениями и присваивания можно производить только над переменными одного типа. Иногда это приведение выполняется автоматически, например:
int v1 = 4; double v2 = v1 + 0.123;
В этом случае, при выполнении второй строки в первую очередь будет выполнено приведение переменной v1 к типу double, а потом сложение. Но следующий код вызовет ошибку:
double v2 = "4" + 0.123;
Так как “4” – это значение строкового типа, а 0.123 имеет тип double.
К языкам с сильной типизацией относятся C#, Java, Python.
В языках со слабой типизацией таких ограничений нет, например, на C вы можете написать следующее:
char * str = "hello"; double value = str + 0.123;
В результате код скомпилируется, если его запустить, то в переменной double будет лежать численное значение.
Языки со слабой типизацией – это C, C++.
Явная типизация предполагает явное указание типа переменной:
int value = 1;
В этом примере, мы объявляем переменную value типа int и явно это указываем.
В языке с неявной типизацией этого делать не нужно, пример на Python
value = 1
Какой тип типизации, явный или неявный, используется не зависит от того компилируемый язык или интерпретируемый, это определяется дизайном языка. Например в C# вы можете использовать оба подхода, в первом случае код будет выглядеть так:
double value = 0.123;
Во втором так:
var value = 0.123;
Символы
В C# символы представлены не 8-разрядным кодом, как во многих других языках
программирования, например , а 16-разрядным кодом, который называется юникодом (Unicode). В юникоде набор символов представлен настолько широко, что он охватывает символы практически из всех естественных языков на свете. Если для многих
естественных языков, в том числе английского, французского и немецкого, характерны
относительно небольшие алфавиты, то в ряде других языков, например китайском,
употребляются довольно обширные наборы символов, которые нельзя представить
8-разрядным кодом. Для преодоления этого ограничения в C# определен тип char,
представляющий 16-разрядные значения без знака в пределах от 0 до 65 535. При этом
стандартный набор символов в 8-разрядном коде ASCII является подмножеством юникода в пределах от 0 до 127. Следовательно, символы в коде ASCII по-прежнему остаются действительными в C#.
Для того чтобы присвоить значение символьной переменной, достаточно заключить это значение (т.е. символ) в одинарные кавычки:
Несмотря на то что тип char определен в C# как целочисленный, его не следует
путать со всеми остальными целочисленными типами. Дело в том, что в C# отсутствует автоматическое преобразование символьных значений в целочисленные и обратно.
Например, следующий фрагмент кода содержит ошибку:
Наравне с представлением char как символьных литералов, их можно представлять
как 4-разрядные шестнадцатеричные значения Unicode (например, ‘\u0041’), целочисленные значения с приведением (например, (char) 65) или же шестнадцатеричные значения (например, ‘\x0041’). Кроме того, они могут быть представлены в виде .
Типы указателей
Для любого типа T существует тип «указатель на T».
Переменные могут быть объявлены как указатели на значения различных типов с помощью символа . Для того чтобы определить тип переменной как указатель, нужно предварить её имя звёздочкой.
char letterC = 'C'; char *letter = &letterC; //взятие адреса переменной letterC и присваивание в переменную letter printf("This code is written in %c.", *letter); //"This code is written in C."
Помимо стандартных типов, можно объявлять указатели на структуры и объединения:
struct Point { int x,y; } A; A.x = 12; A.y = 34; struct Point *p = &A; printf("X: %d, Y: %d", (*p).x, (*p).y); //"X: 12, Y: 34"
Для обращения к полям структуры по указателю существует оператор «стрелочка» , синонимичный предыдущей записи: — то же самое, что и .
Поскольку указатель — тоже тип переменной, правило «для любого типа T» выполняется и для них: можно объявлять указатели на указатели. К примеру, можно пользоваться :
int w = 100; int *x = &w; int **y = &x; int ***z = &y; printf("w contains %d.", ***z); //"w contains 100."
Существуют также указатели на массивы и на функции. Указатели на массивы имеют следующий синтаксис:
char *pc10]; // массив из 10 указателей на char char (*pa); // указатель на массив из 10 переменных типа char
— массив указателей, занимающий байт (на распространённых платформах — обычно 40 или 80 байт), а — это один указатель; занимает он обычно 4 или 8 байт, однако позволяет обращаться к массиву, занимающему 10 байт: , но .
Указатели на массивы отличаются от указателей на первый элемент арифметикой. Например, если указатели указывает на адрес 2000, то указатель будет указывать на адрес 2010.
char (*pa); char array10 = "Wikipedia"; pa = &array; printf("An example for %s.\n", *pa); //"An example for Wikipedia." printf("%c %c %c", (*pa), (*pa), (*pa)); //"i i i"
Арифметическое переполнение и деление на нульArithmetic overflow and division by zero
Если результат арифметической операции выходит за пределы диапазона возможных конечных значений соответствующего числового типа, поведение арифметического оператора зависит от типа его операндов.When the result of an arithmetic operation is outside the range of possible finite values of the involved numeric type, the behavior of an arithmetic operator depends on the type of its operands.
Целочисленное арифметическое переполнениеInteger arithmetic overflow
Деление целого числа на ноль всегда вызывает исключение DivideByZeroException.Integer division by zero always throws a DivideByZeroException.
В случае целочисленного арифметического переполнения итоговое поведение определяется контекстом проверки переполнения, который может быть проверяемым или непроверяемым:In case of integer arithmetic overflow, an overflow checking context, which can be checked or unchecked, controls the resulting behavior:
- Если в проверяемом контексте переполнение возникает в константном выражении, происходит ошибка времени компиляции.In a checked context, if overflow happens in a constant expression, a compile-time error occurs. В противном случае, если операция производится во время выполнения, возникает исключение OverflowException.Otherwise, when the operation is performed at run time, an OverflowException is thrown.
- В непроверяемом контексте результат усекается путем удаления старших разрядов, которые не помещаются в целевой тип данных.In an unchecked context, the result is truncated by discarding any high-order bits that don’t fit in the destination type.
Вместе с проверяемыми и непроверяемыми операторами вы можете использовать операторы и , чтобы управлять контекстом проверки переполнения, в котором вычисляется выражение:Along with the checked and unchecked statements, you can use the and operators to control the overflow checking context, in which an expression is evaluated:
По умолчанию арифметические операции выполняются в непроверяемом контексте.By default, arithmetic operations occur in an unchecked context.
Арифметическое переполнение с плавающей запятойFloating-point arithmetic overflow
Арифметические операции с типами и никогда не вызывают исключение.Arithmetic operations with the and types never throw an exception. Результатом арифметических операций с этими типами может быть одно из специальных значений, представляющих бесконечность и объект, не являющийся числовым:The result of arithmetic operations with those types can be one of special values that represent infinity and not-a-number:
Для операндов типа арифметическое переполнение всегда вызывает исключение OverflowException, а деление на нуль всегда вызывает исключение DivideByZeroException.For the operands of the type, arithmetic overflow always throws an OverflowException and division by zero always throws a DivideByZeroException.
Работа с типом doubleWork with the double type
Числовой тип представляет число с плавающей запятой двойной точности.The numeric type represents a double-precision floating point number. Эти термины могут быть новыми для вас.Those terms may be new to you. Число с плавающей запятой можно использовать для представления нецелых чисел, которые могут быть очень большими или малыми.A floating point number is useful to represent non-integral numbers that may be very large or small in magnitude. Число двойной точности — это относительный термин, описывающий количество двоичных разрядов, используемых для хранения значения.Double-precision is a relative term that describes the number of binary digits used to store the value. Числа двойной точности имеют в два раза больше двоичных символов по сравнению с числами одиночной точности.Double precision numbers have twice the number of binary digits as single-precision. На современных компьютерах числа двойной точности используются чаще, чем одиночной.On modern computers, it’s more common to use double precision than single precision numbers. Числа одиночной точности объявляются с помощью ключевого слова .Single precision numbers are declared using the keyword.
Рассмотрим их.Let’s explore. Добавьте следующий код и просмотрите результат:Add the following code and see the result:
Обратите внимание, что ответ включает десятичную долю частного.Notice that the answer includes the decimal portion of the quotient. Попробуйте более сложное выражение с типом double:Try a slightly more complicated expression with doubles:. Диапазон значений типа double гораздо больше, чем диапазон значений целых чисел.The range of a double value is much greater than integer values
Добавьте следующий фрагмент после написанного кода:Try the following code below what you’ve written so far:
Диапазон значений типа double гораздо больше, чем диапазон значений целых чисел.The range of a double value is much greater than integer values. Добавьте следующий фрагмент после написанного кода:Try the following code below what you’ve written so far:
Значения выводятся в экспоненциальном представлении.These values are printed out in scientific notation. Число слева от символа является значащим.The number to the left of the is the significand. Число справа — это показатель степени, который равен 10.The number to the right is the exponent, as a power of 10.
Так же, как десятичные числа в математике, значения double в C# могут содержать ошибки округления.Just like decimal numbers in math, doubles in C# can have rounding errors. Выполните этот код:Try this code:
Вы знаете, что периодическая десятичная дробь не равняется .You know that repeating isn’t exactly the same as .
ЗадачаChallenge
Выполните другие вычисления с большими числами, малыми числами, умножением и делением с помощью типа .Try other calculations with large numbers, small numbers, multiplication, and division using the type. Попробуйте выполнить более сложные вычисления.Try more complicated calculations.
После того как вы решите сложную задачу, поместите написанный код в новый метод.After you’ve spent some time with the challenge, take the code you’ve written and place it in a new method. Присвойте этому методу имя .Name that new method .