Студопедия.Орг Главная | Случайная страница | Контакты | Мы поможем в написании вашей работы!  
 

Преобразование типов



5.1. Преобразование типов в выражениях

Такое преобразование имеет место, когда в выражении смешиваются переменные и константы различных типов. Тогда компилятор преобразует все операнды (элементы выражения) к типу большего операнда (с точки зрения памяти) по следующим правилам:

переменные типа char и short int преобразуются к типу int;

переменные типа float преобразуются к типу double;

если один из пары операндов имеет тип double, другой операнд также преобразуется к double;

если один из пары операндов имеет тип unsigned, другой операнд также преобразуется к unsigned;

Пример 25. Пусть char c; int k; float f; double d, res; … res=(f+d) * (c-k);

Последовательно выполняется преобразование внутри каждой пары операндов до выполнения соответствующей операции. Перед выполнением сложения переменная f преобразуется к типу double и затем суммируются переменные одинаковых типов double. Перед вычитанием с преобразуется к типу int и результат вычитания будет целым. Так как (f+d) имеет тип double, то перед умножением целое (c-i) преобразуется к типу double, и всё выражение будет иметь тип double. Так как переменная слева имеет такой же тип double, то во время присваивания преобразование типов в этом примере не выполняется (см. 5.2).

Есть возможность “заставить” выражение принять определённый тип с помощью операции принудительного преобразования, имеющей следующий вид: (тип) выражение. Здесь в скобках можно записать стандартный или определённый пользователем тип.

Например, часто можно встретить следующую ошибку. Пусть переменная Sum используется для вычисления суммы элементов целочисленного массива размерности n, где n, конечно, целое. Тогда если объявить int Sum, то среднее значение по формуле Aver=Sum/n; будет найдено неправильно, даже если float Aver. Почему? Несмотря на то, что Aver вещественное, мы имеем дело с целочисленным делением, так как и Sum, и n целые. Поэтому при делении будет отброшена дробная часть результата,. Полученное целое значение будет преобразовано к типу float без восстановления отброшенной дробной части и присвоено переменной Aver.

Один из способов преодолеть это — объявить float Sum. А если нам надо, чтобы в других операторах этого же блока или функции переменная Sum была целой? Тогда, оставив int Sum, записываем Aver=(float)Sum/n. В таком случае при вычислении частного произойдёт “временное” преобразование Sum из int во float, а в остальных операторах как до, так и после этого присваивания Sum будет иметь тот тип, который записан при объявлении, т. е. целый. Поэтому если, например, записать cout << Sum; то сумма будет выведена как целая величина.

Пример 26. Дан код: float f=100.5; cout<<(int)f/6<<” “ << int)f/6.<< " "<<f/6<< " "<<f/6.; Что будет выведено?

Ответ: 16 16.6667 16.75 16.75

Объяснить результат.

5.2. Преобразование типов при присваивании

Что получится, если бы в предыдущем примере res=(f+d) * (c-i); переменная res имела тип, отличный от double, например, целый? Тогда используется следующее правило преобразования типов при присваивании: значение справа от оператора присваивания (значение выражения) преобразуется к типу переменной, стоящей слева. В результате получилась бы целая часть выражения справа.

Пример 27. Пусть char c; int k; float f; double d;

a) При присваивании c=k в переменной c остаются младшие 8 битов переменной k. Когда происходит преобразование из целого числа int или short к символу char, из целого int — к короткому целому short, то старшие биты теряются.

b) В результате присваиваний f=c; f=k; получается целое число, преобразованное к формату с плавающей точкой.

При преобразовании из int в float или из float в double точность не увеличивается, а всего лишь меняется формат представления данных.

Пример 28. Дан код:

float f2 =100.5, r1=(int)f2/6, r2=(int)f2/6., r3=f2/6, r4=f2/6.;

cout<<r1<< " "<<r2<<" "<<r3<< " "<<r4;

Что будет выведено?

Ответ: 16 16.6667 16.75 16.75

Объяснить, какие преобразования выполнены.

Пример 29. Дан код:

int f2 =100.5, r21=(int)f2/6, r22=(int)f2/6., r23=f2/6, r24=f2/6;

cout<<r21<<" "<<r22<<" "<<r23<<" "<<r24;

Что будет выведено?.

Ответ: 16 16 16 16

Объяснить, какие преобразования выполнены.

Упражнения и тесты

Целый тип. Битовые операции.

1. Что будет выведено? int a=170, r = a & 15; cout<<r;

r = a | 8; cout<<endl<<r<<endl;

if ((a & 8) == 8) cout<<"Yes"; else cout<<"No";

Решение. Число 170 переводим в шестнадцатеричную систему счисления делением на 16. Получим 17010=AA16. Каждую шестнадцатеричную цифру запишем в виде двоичной тетрады и добавим необходимое количество незначащих нулей. Получим 00000000000000000000000010101010.

1510 = 11112. Учитывая правила выполнения операции &, выведем десятичное число 10, т. е. с помощью этой операции всегда выделяется последняя шестнадцатеричная цифра числа.

Так как 810=10002 и принимая во внимание правила выполнения операции | (битовое или), получим то же число 170.

Так как в двоичном представлении числа 8 есть всего одна единица, то результатом операции a & 8 будет либо 0, либо 8 =10002 в зависимости от того, что находится в 3–м справа бите числа a (нумерация битов с нуля). В нашем примере получим 8, и будет выведено “YES”, что означает, что в 3–м справа бите исходного числа a была единица.

2. Определить результат:

unsigned short a; cin>>a; a=a & 0xFFF7; cout<<a;

Решение. Введем, например, число 26. В двоичной системе счисления это 0000000000011010. Так как FFF716=11111111111101112, то операция &(битовое и) оставит без изменения все биты, кроме третьего справа. Независимо от того, что было в этом бите (0 или 1), получится нуль, т. е. мы “выключили” третий справа бит. В результате получим 00000000000100102=18, т. е. будет выведено число 18. Если введем, например, число 23, то это число не изменится, так как в третьем бите был 0.

3. Пусть int a=-8, b=23. Что получится в результате выполнения следующей части программы: printf (“%d %X %d %X”, a & b,a | b,a ^ b,~a);

4. Найти значение переменной r, объявленной как int r, если:

а) r= ~(100>>2) & ~(–10) | 0x10; b ) r=162 | 0x10A & 111;

c) r= –10 & 1|4; d) r=(123<<4)& 123.

5. Найти значение этого же выражения из предыдущего упражнения, если переменная объявлена как unsigned short r.

6. Найти r3=30 ^ –1707, если:

a) short r3, b) unsigned short r3.

7a. Пусть в ячейке, объявленной short a, хранится следующая двоичная последовательность:

а) 0000001001001001; b) 1100000000001000;

c) 1111111111111000; d) 1000000000000000.

Что это за число в десятичной системе счисления? шестнадцатеричной системе счисления?

7b. Выполнить предыдущее упражнение, если переменная объявлена как unsigned short a.

8. Как включить 4-й справа бит, т. е. поместить туда единицу независимо от того, какое там было значение? Нумерация битов с нуля.

9. Как заменить значение 2–го справа бита на противоположное значение, т. е. нуль на единицу, а единицу на нуль? Нумерация битов с нуля.

Логический тип.

10. Пусть bool b1, b2, b3. Записать оператор if и операторы присваивания, которые выполняют те же действия, что и оператор

a) b1= b2 || b3; b) b1=b2 || b3 && b4;

c) b1=(b2 || b3) && b4; d) b1=!(b2 && b3 || b4).

Решение: a) if (b2) b1=true; else b1=b3;

11. Записать с помощью логических операций и оператора присваивания,не используя оператор if:

bool b1, b2, b3,r; if (!b1) r=false; else if (!b2) r=false; else r=b3;

12. Нарисовать область плоскости, в которой и только в которой для вещественных величин x и y следующее логическое выражение истинно:

а) (fabs(x) < 1) > (fabs(y) < 1);

b)! (fabs(x) < 1) = = (fabs(y) < 1);

c)! ((fabs(x) < 1) = = (fabs(y) < 1)).

Решение. a) Надо найти область плоскости, в которой и только в которой одновременно первое неравенство истинно, а второе ложно, т. е. точки, для которых выражение (fabs(x)<1) && (fabs(y)>=1) истинно.

b) !(fabs(x) < 1) равносильно неравенству (fabs(x) >= 1). Поэтому надо найти область плоскости, в которой и только в которой выражение

(fabs(x)>=1) &&(fabs(y)<1) || (fabs(x)<1) &&(fabs(y)>=1) истинно.

c) Сначала определяем область, в которой и только в которой выражение (fabs(x)<1) && (fabs(y)<1) || (fabs(x)>=1) && (fabs(y)>=1) истиннo. Это был бы ответ, если бы не было операции отрицания. Операция отрицания в качестве ответа оставит точки, не вошедшие в эту область.

13. Записать следующее логическое выражение, используя операции логического умножения и сложения (&&, ||) и не используя сравнение логических величин: a) (y>x) = = (x>0); b) (y > x)!= (x > 0);

c) !((y > x) > (x>0)); d )! (y > x) > (x > 0).

Нарисовать область плоскости, в которой и только в которой записанное логическое выражение истинно.

14. Записать логическое выражениес помощью сравнения логических величин, не используя операций && и ||:

a) x*x+y*y > 1 && y <= x;

b) x*x+y* y> 1 && y <= x || x*x+y*y <= 1 && y > x;

c) x>0 && y > 0 || x <= 0 && y <= 0.

Нарисовать область плоскости, в которой и только в которой записанное логическое выражение истинно.

15. Не используя логических операций, записать выражение, принимающее значение true тогда и только тогда, когда точка плоскости с координатами (x, y) принадлежит первой четверти, включая и оси координат, или третьей четверти, не включая оси координат.

16. Объяснить работу следующей программы:

float x,y; bool lg; cin>>x>>y;

while (!(x==100 && y==100))

{

lg=x>0; cout<<" "<<lg<<" "<<(y>0)<<" "<<(lg > (y>0));

if (lg > (y>0)) cout<<" YES "; else cout<<" NO";

cin>>x>>y;

}

17. Операторы

int x=8, y=4;

cout<<(x&y)<<" "<<(x&&y)<<" " <<(x|y)

<<" "<<(x||y) <<" "<<(y<x<1)<<" "<<(x<y<1);

выведут 0 1 12 1 0 1. Объяснить результат.

Символьный тип.

18. Объяснить выполнение printf("%c %d", a, a);

Вариант 1. Если int a; и вводим число 98, то выведем b 98, т. е. по формату %c выводится символ, код которого хранится в переменной a, а по формату %d — целое число, код этого символа.

Вариант 2. Этот же результат получим, если объявим char a; и введём символ ‘ b’.

19. Что будет выведено и почему?

1) char ch; cin>>ch; cout<< (ch*2);

если введём 1) 1? 2) d?:

2) char CH=1; cout<<” “<<(CH*2);

3) char ch2=’1’; cout<<” “<<(ch2*2);

4) printf (“ \n %c %d %c %d %c %d”, ch, ch, CH, CH, ch2, ch2);

Объявление и инициализация, как в 1), 2), 3).

5) int ci; cin>>ci; printf(“\n %c %d”, ci,ci);

если введём 50?

Вещественный тип

20. a) float f1=1., f2=0.1, f3=-1., f4=-0.1;

b) float f1=10., f2=10.1, f3=-10., f4=-10.1;

Как эти числа представляются в памяти компьютера?

Задачи





Дата публикования: 2015-02-18; Прочитано: 278 | Нарушение авторского права страницы | Мы поможем в написании вашей работы!



studopedia.org - Студопедия.Орг - 2014-2024 год. Студопедия не является автором материалов, которые размещены. Но предоставляет возможность бесплатного использования (0.014 с)...