Полезное:
Как сделать разговор полезным и приятным
Как сделать объемную звезду своими руками
Как сделать то, что делать не хочется?
Как сделать погремушку
Как сделать так чтобы женщины сами знакомились с вами
Как сделать идею коммерческой
Как сделать хорошую растяжку ног?
Как сделать наш разум здоровым?
Как сделать, чтобы люди обманывали меньше
Вопрос 4. Как сделать так, чтобы вас уважали и ценили?
Как сделать лучше себе и другим людям
Как сделать свидание интересным?
Категории:
АрхитектураАстрономияБиологияГеографияГеологияИнформатикаИскусствоИсторияКулинарияКультураМаркетингМатематикаМедицинаМенеджментОхрана трудаПравоПроизводствоПсихологияРелигияСоциологияСпортТехникаФизикаФилософияХимияЭкологияЭкономикаЭлектроника
|
Явное и неявное преобразование типа
В параграфе операции кратко уже описывалась операция преобразования типа. В этом параграфе операция преобразования типа будет разобрана полностью с соответствующими примерами. Операция явного преобразования типа в языке Си++ имеет две различные формы. Каноническую, унаследованную от языка С, и функциональную, которые имеют следующий формат: (type) операнд // каноническая форма type (операнд) // функциональная форма где type – основной, составной или определенный пользователем тип данных; операнд – константа, переменная или структурированный объект произвольного типа. Результатом выполнения операции явного преобразования типа является создание неименованного объекта типа type, который инициализируется значением операнда. При явном преобразовании типа может происходить или не происходить потеря точности, хотя компилятор всегда старается по возможности преобразовать число с максимальной точностью. Всё зависит от того, из какого в какой тип происходит преобразование. Так, переменная типа long имеет 10 значащих цифр, а переменная типа float - только семь. Поэтому при преобразовании типа из long в float компилятор вынужден отбросить младшие разряды числа, сохранив при этом порядок и старшие разряды числа. Примеры: long k = 123456789; /* Определение переменной k (задаётся её тип – long и значение) */ float g = float(k); /* В соответствии с таблицей приоритетов операций сначала выполняется операция преобразования типа, т.е. float(k). Результатом выполнения этой операции является создание неименованной переменной типа float, которая инициализируется в данном случае с потерей точности значением переменной k. При этом ни тип, ни значение переменной k не изменяются. Далее определяется переменная g типа float, которая инициализируется значением неименованной переменной. Область существования неименованной переменной – данная строка программы. При переходе к следующей строке программы неименованная переменная уничтожается.*/ cout<<”\n float(k) = “<<float(k); /*Оператор выведет на экран (float(k) = 1.234567e+08) результат операции преобразования типа, на примере которого можно видеть, что младшие разряды отброшены. */ double pi = 3.14159; cout<<”\n int(pi) = “<<int(pi); /*Результатом выполнения этих строк программы будет вывод строки программы int(pi) = 3 на экран монитора. Дробная часть числа отброшена. */ cout<<”\n double(k) = “<<double(k); /* Результат (double(k) = 1.23456789е+08) потеря точности при преобразовании типа не происходит, так как число double имеет 15 значащих цифр. */ Кроме явного преобразования типа для арифметических операций и арифметических типов данных в языке Си++ определена операция неявного преобразования типа. Суть её состоит в том, что если в арифметической операции участвуют два операнда разного типа, то происходит неявное преобразование типа одного операнда к типу другого и только после этого происходит выполнение операции. Из двух возможных типов операндов компилятор всегда выбирает наиболее точный (в соответствии со схемой, изображенной на рис. 3.2) и преобразует к нему один из операторов. Этот же тип является типом результата операции. Рис. 3.2. Схема арифметических преобразований типов, гарантирующих сохранение значимости
Из рис. 3.2 видно, что если в арифметической операции участвуют два операнда, например, типа int и double, то операнд типа int будет неявно преобразован к типу double, так как double точнее int, затем выполнится арифметическая операция, результат которой будет иметь тип double. Пример: int f = 2; double e = 2.71; f = e*f; /*f неявно преобразуется к типу double; выполняется операция умножения; результат операции равен 5.42 и имеет тип double. */ f= 1-e; /* константа единица имеет тип int, который по умолчанию преобразуется к типу double, выполняется операция вычитания; результат операции равен -1.71 типа double.*/ При записи арифметических выражений необходимо помнить, что правило неявного преобразования типа и все рассуждения, связанные с сохранением точности, относятся не ко всему выражению в целом, а к отдельно взятым операциям. Так, например: int a =1, b = 2; double f = 1; f = a/b*f+a*f/b; cout<<”\n f = “<<f; /* На экран монитора выводится результат f = 0.5, хотя логичнее было бы предположить, что результат должен быть равен единице. */ Полученный результат объясняется тем, что операции в выражении выполняются последовательно друг за другом в строгом соответствии с их рангом и направлением ассоциативности. Следовательно, первой выполнится операция (a/b). Оба операнда у неё имеют тип int, поэтому неявного преобразования типа не происходит; результатом операции является неименованная переменная типа int, значение которой равно нулю (дробная часть при делении целых чисел отбрасывается). Второй выполняется операция умножения неименованной переменной типа int на переменную f типа double, в результате умножения нуля типа int на единицу типа double получаем ноль типа double. Далее выполняется операция (а*f), в результате получаем единицу типа double. Единица типа double делится на переменную b типа int, получаем 0.5 типа double. Ноль типа double складывается с 0 типа double, получаем 0.5 типа double. Результат выполнения выражения a/b*f+a*f/b равен 0.5 типа double. Таким образом, потеря точности произошла во время выполнения одной из операций (в данном случае a/b) и значение всего выражения стало не тем, которое можно было бы ожидать. Приведём ещё несколько примеров int a = 10000, b = 5; double c = 1.; c = a*b/c; /* потеря точности происходит при выполнении операции a*b. Так как оба операнда имеют тип int, то результат тоже будет иметь тип int. Но в результате выполнения операции a*b получается значение 50000, которое выходит за допустимый диапазон значений переменных типа int. Поэтому значение выражения a*b/c будет непредсказуемо. */ unsigned int a = 5, b=70; double k = 1; k = k*(a-b);. /*Результат выполнения операции (a-b) имеет тип unsigned int, а число –65 выходит за допустимый диапазон значений типа unsigned int, поэтому значение выражения k*(a-b) будет непредсказуемо. */ k = 1/2*b; /*Значение выражения 1/2*b равно нулю. Так как первой выполняется операция деления, оба операнда - целые константы. Следовательно, результат выполнения операции тоже будет иметь тип int и будет равен нулю (при делении целых операндов дробная часть отбрасывается). Чтобы получить правильный результат, нужно сделать хотя бы одну константу константой вещественного типа. Для этого рядом с ней нужно поставить точку 1./2*b. */ Таким образом, при вычислении арифметических выражений может быть потеряна точность при выполнении какой-то операции или из-за отбрасывания дробной часть, или из-за переполнения разрядной сетки машины. Чтобы этого не происходило, лучше в выражении использовать только вещественные типы данных. Неявное преобразование типа над арифметическими типами данных происходит также при выполнении операции присваивания (=). Операция заключается в том, что если арифметический тип данных, стоящий справа от операции (=), не совпадает с типом левого арифметического операнда, то происходит неявное преобразование типа правого операнда к типу левого в независимости от того, какой из типов точнее и теряется при выполнении этой операции точность или нет. Пример: int k; double pi= 3.1415; k = pi; /*Создаётся неименованная переменная типа int, которая инициализируется значением переменной pi; при этом происходит потеря точности. Ни тип, ни значение переменной pi не изменяются. После этого значение неименованной переменной присваивается переменной k.*/ Таким образом, правило преобразования типа данных по умолчанию над арифметическими типами данных для арифметических операций и операции присваивания отличаются друг от друга. Date: 2015-05-22; view: 803; Нарушение авторских прав |