ВУЗ: Не указан
Категория: Не указан
Дисциплина: Не указана
Добавлен: 11.12.2025
Просмотров: 3253
Скачиваний: 1
Процессоры Pentium используют небольшой трюк, который несколько снижает уш занную неприятность,— при работе они применяют специальный формаа в котором для числа с плавающей точкой выделяется 80 бит. При округлении тако| го числа к 64-битовому почти всегда получается результат, который вы ожидаете.
Скорость вычислений
Процессоры х86, использующиеся на старых компьютерах под управление]! Windows, выполняли действия над целыми числами существенно быстрее, чем над чис| лами с плавающей точкой. В настоящее время эта проблема так остро не стоит.
Отношение скоростей работы процессора Pentium III при простом (пожалуй, слиш] ком простом) тесте, состоящем в 300000000 сложений и вычитаний целых чисел и чисем с плавающей точкой, оказалось равным примерно 3 к 1. То есть вместо одного сложешя d o u b l e можно сделать три сложения i n t . (Вычисления с применением умножения и делений могут привести к другим результатам.)
Ограниченность диапазона
В прошлом переменные с плавающей точкой могли представлять значительно боль ший диапазон чисел, чем целые. Сейчас диапазон представления целых чисел существ венно вырос — стоит вспомнить о типе l o n g .
Даже простой тип f l o a t способен хранить очень большие числа, но числа значащих цифр у него ограничено примерно шестью. Например, 12345678 9F означает то же, что и 123456000F . (О том, что такое F в приведенных заган сях, вы узнаете немного позже.)
Как уже объяснялось в предыдущих разделах, и целые, и десятичные числа имеют свои недостатки. Переменным с плавающей точкой присущи проблемы, связанные с во просами округления из-за недостаточной точности представления, целые переменные не могут представлять числа с дробной частью. Бывают ситуации, когда совершенно необ ходимо иметь возможность получить лучшее из обоих миров, а именно числа, которые:
•S подобно числам с плавающей точкой, способны иметь дробную часть;
Sподобно целым числам, должны представлять точные результаты вычислений — т.е. 12.5 должно быть равно 12.5, и ни в коем случае не 12.500001.
К счастью, в С# есть такой тип чисел, называющийся d e c i m a l . Переменная типа d e c i m a l в состоянии представлять числа от 10"28 до 1028 — вполне достаточный диапа зон значений! И все это делается без проблем, связанных с округлением.
О б ъ я в л е н и е п е р е м е н н ы х т и п а decimal
Переменные типа d e c i m a l объявляются и используются так же, как и переменные других типов:
64 |
Часть II. Основы программирования в С# |
decimal |
ml; |
// |
Хорошо |
decimal m2 = 100 ; |
// |
Лучше |
|
decimal |
m3 = 100M; |
// |
Идеально |
Объявление ml выделяет память для переменной ml без ее инициализации. Пока вы не присвоите значение этой переменной, оно будет неопределенным. В этом нет особой проблемы, так как С# не позволит вам использовать переменную без начального при своения ей какого-либо значения.
Второе объявление создает переменную т2 и инициализирует ее значением 100. В этой ситуации неприятным моментом оказывается то, что 100 имеет тип i n t . Поэтому С# вы нужден конвертировать i n t в d e c i m a l перед инициализацией. К счастью, С# понимает, чего именно вы добиваетесь, и выполняет эту инициализацию для вас.
Лучше всего использовать такое объявление, как объявление переменной тЗ с кон стантой 10ОМ типа decimal . Буква М в конце числа указывает, что данная константа имеет тип decimal, так что никакого преобразования не требуется.
Сравнение д е с я т и ч н ы х , ц е л ы х ч и с е л и чисел с плавающей т о ч к о й
Создается впечатление, что числа типа d e c i m a l имеют лишь одни достоинства и ли шены недостатков, присущих типам i n t и double . Переменные этого типа обладают широким диапазоном представления и не имеют проблем округления.
Однако у чисел decimal есть свои неприятности. Во-первых, поскольку они имеют дробную часть, они не могут использоваться в качестве счетчиков, например, в циклах, о ко торых пойдет речь в главе 5, "Управление потоком выполнения".
Вторая проблема не менее серьезна, и заключается в том, что вычисления с этим ти пом чисел гораздо медленнее, чем с простыми целыми числами или даже с числами с плавающей точкой. В уже упоминавшемся тесте с 300000000 сложений и вычитаний работа с числами d e c i m a l примерно в 50 раз медленнее работы с числами i n t . Это от ношение становится еще хуже для более сложных операций. Кроме того, большинство математических функций, таких как синус или возведение в степень, не имеют версий для работы с числами decimal .
Понятно, что числа типа d e c i m a l наиболее подходят для финансовых приложений, где исключительно важна точность, но само количество вычислений относительно невелико.
Логичен ли логический tnun?
И наконец, о переменных логического типа. Тип b o o l имеет только два значения — true и false . Это не шутка — целый тип переменных придуман для работы только с двумя значениями.
Ранее программисты на С и С++ использовали нулевое значение переменной типа i n t для обозначения f a l s e и ненулевое — для обозначения t r u e . В С# этот фокус не проходит.
Переменная типа b o o l объявляется следующим образом: bool thisIsABool = t r u e ;
Нет никаких путей для преобразования переменных b o o l в другой тип переменных (даже если бы вы могли это делать, это бы не имело никакого смысла). В частности, вы
Глава 3. Объявление переменных-значений |
65 |
не можете |
преобразовать b o o l |
в s t r i n g |
(чтобы f a l s e стало |
в i n t (чтобы, скажем, f a l s e превратилось в 0) или " f a l s e " ) .
Программа, которая в состоянии заниматься только вычислениями, могла бы устроить разве что математиков, страховых агентов и военных (да-да— первые вычислительные машины были созданы для расчета таблиц артиллерийских стрельб). Однако в большинст ве приложений программы должны работать не только с цифрами, но и с буквами.
С# рассматривает буквы двумя различными путями — как отдельные символы типа c h a r и как строки символов типа s t r i n g .
Т и п char
Переменная типа c h a r способна хранить только один символ. Символьная константа выглядит как символ, окруженный парой одинарных кавычек:
c h a r с = ' а' ;
Вы можете хранить любой символ из латинского алфавита, кириллицы, арабского, иврита, японских катаканы и хираганы и массы японских, китайских или корейских ие роглифов.
Кроме того, тип c h a r может использоваться в качестве счетчика, т.е. его можно применять в циклах, о которых вы узнаете в главе 5, "Управление потоком выполнения". У символов нет никаких проблем, связанных с округлением.
Переменные типа c h a r не включают информации о шрифтах, так что в пере менной c h a r может храниться, например, вполне корректный иероглиф, но при выводе его без использования соответствующего шрифта вы увидите на экране только мусор.
С п е ц и а л ь н ы е с и м в о л ы
Некоторые символы являются непечатными в том смысле, что вы ничего не увидите при выводе их на экран или на принтер. Наиболее очевидным примером такого символа является пробел ' 1 (кавычка, пробел, кавычка). Другие символы не имеют буквенного эквивалента — например, символ табуляции. Для указания таких символов С# использу ет обратную косую черту, как показано в табл. 3.3.
66 |
Часть II. Основы программирования в С# |
Тип string
Еще одним распространенным типом переменных является s t r i n g . Приведенные да лее примеры показывают, как объявляются и инициализируются переменные этого типа.
// Объявление с отложенной инициализацией string s o m e S t r i n g l ;
someStringl = "Это строка" ;
// Инициализация при объявлении string someString 2 = "Это строка" ;
Константа типа s t r i n g , именуемая также строковым литералом, представляет собой набор символов, окруженный двойными кавычками. Символы в строке могут включать специальные символы, показанные в табл. 3.3. Строка не может быть перенесена на но вую строку в исходном тексте на С#, но может содержать символ новой строки, как по казано в следующем примере:
// Неверная запись строки
string someStrin g = "Это строка
иэто строка" ;
//А вот так - верно
string someStrin g = "Это строка\пи эт о строка" ;
При выводе на экран при помощи вызова C o n s o l e . W r i t e L i n e вы увидите текст, размещенный в двух строках:
Это строка и это строка
Строка не является ни перечислимым типом, ни типом-значением — в процессоре не существует встроенного типа строки. К строкам применим только один распространенный оператор — оператор сложения, который просто объединяет две строки в одну, например: string s = "Это предложение . " + " И эт о тоже. " ;
Приведенный код присваивает строке s значение: "Это предложение . И эт о тоже ."
Строка без символов, записанная как "" (пара двойных кавычек), является корректной строкой для типа s t r i n g , и называется пустой строкой. Пустая строка отличается от нулевого символа ' \ 0 ' и от строки, содержащей любое количество пробелов (" ") .
Кстати, все остальные типы данных в этой главе — типы-значения (value types). Строковый тип типом-значением не является.
Все инструкции С# должны быть реализованы как машинные команды процессо р а — процессора Intel в случае PC. Эти процессоры также имеют собственную концепцию переменных. Например, процессор Intel содержит восемь внутренних хранилищ, именуемых регистрами, каждый из которых может хранить одно зна чение i n t . Не вдаваясь в детали функционирования процессора, можно сказать, что все типы, описываемые в данной главе, за исключением decima l и s t r i n g , являются встроенными для процессора. Таким образом, существует машинная
Глава 3. Объявление переменных-значений |
67 |
команда, суть которой в следующем: прибавить один i n t к другому. Имеется I аналогичная команда и для сложения d o u b l e .
Кроме того, переменные описанных типов (опять же, за исключением s t r i n g ) I имеют фиксированную длину. Переменные типа с фиксированной длиной всегда за-1 нимают одно и то же количество памяти. Так что при присваивании а = Ь С# может! поместить значение b в а без каких-либо дополнительных мер, разработанных для I типов переменной длины. Эта характеристика дает этим типам переменных имя ти-1
пы-значения.
Типы i n t , d o u b l e , b o o l и их "близкие родственники" наподобие беззнаково-1 го i n t являются встроенными типами. Встроенные типы переменных и тип I d e c i m a l известны также как типы-значения. Тип s t r i n g не относится ни I к тем ни к другим.
Типы, о которых речь пойдет в главе 6, "Объединение данных — классы и массивы", определяемые программистом и известные как ссылки, не являются ни встроенными, ни типами-значениями. Тип s t r i n g является ссылочным типом, хотя компилятор С# рас сматривает его специальным образом в силу его широкой распространенности.
Сравнение string и char
Хотя строки имеют дело с символами, тип s t r i n g существенно отличается от типа c h a r . Понятно, что имеются некоторые тривиальные отличия. Так, символ помещается в одинарные кавычки, а строка — в двойные. Кроме того, тип c h a r — это всегда один символ, так что следующий код не имеет смысла — ни в плане сложения, ни в плане
конкатенации: |
|
|
c h a r c l = |
' а ' ; |
|
c h a r |
с 2 = |
' Ь 1 ; |
c h a r |
с З = c l + с 2 ; |
|
На самом деле этот код почти компилируем, но его смысл существенно отли чается от того, который мы ему приписываем. С# преобразует cl и с2 в значе ния типа i n t , представляющие собой числовые значения соответствующих символов, после чего складывает полученные значения. Ошибка возникает при попытке сохранить полученный результат в с З , так как при размещении значе ния типа i n t в переменной меньшего размера c h a r данные могут быть поте ряны. В любом случае, эта операция не имеет смысла.
С другой стороны, строка может быть любой длины. Таким образом, конкатенация двух строк вполне осмысленна:
s t r i n g s i |
= |
" а " ; |
|
s t r i n g s 2 |
= |
" b " ; |
|
s t r i n g s 3 |
= |
s i + s 2 ; |
/ / Р е з у л ь т а т — " a b " |
В качестве части своей библиотеки С# определяет целый ряд строковых операций, которые будут описаны в главе 9, "Работа со строками в С#".
68 |
Часть II. Основы программирования в С# |