2. Основни типове данни

 
Arithmetic is being able to count up to twenty
without taking off your shoes.
Mickey Mouse
 
Числени типове - цели числа и числа с плаваща точка. Константи и променливи.
    Да се намери стойността (в долари) на купчина американски монети (1 penny = 1 цент, 1 dime = 10 цента, 1 quarter = 25 цента). Купчината съдържа 8 монети от 1 цент, 4 монети от 10 цента и 3 монети от 25 цента.
// coins1.cpp
#include <iostream>
using namespace std;

int main()
{
 int pennies = 8;   /*променлива pennies, константа 8 */
 int dimes = 4;     /*променлива dimes, константа 4   */
 int quarters = 3;  /*променлива quarters, константа 3*/
 double total = pennies*0.01 + dimes*0.10 + quarters*0.25;
/* обща стойност на монетите */
 cout << "Total value = " << total << "\n";
 return 0;
}

Total value = 1.23

* Цели числа (integer numbers):   8, -54, 1289
* Десетични дроби или числа с плаваща точка (floating point numbers): 0.01, 12.5, 73.0, 21.0E2, 5.34E-3, -22.0E4
* Символни имена (идентификатори):
  -- редица от букви, цифри и знака _, като първият символ е буква;
  -- отличават се малки и главни букви;
  -- запазени думи: main, return, int, double, ...;
  -- имена на променливи.
* Характеристики на променлива: име, тип, стойност. В оператора за дефиниране на променлива се задават задължително типа и името на променливата и по желание началната й стойност. Например в оператора
  int dimes = 4;
типа на променливата е int, името - dimes и стойността 4.
* Оператор за изход, обекта "екран":
  cout << "Total value = ";             /* извежда низ */
  cout << total;     /* извежда стойност на променлива */
  cout << "\n";     /* специален символ за край на ред */
* Коментар - не се обработва от компилатора:
/* коментар между знаците за начало и край на коментар */
// коментар - до края на реда.



Големина и точност на числата в С++.
** Целочислени типове:
- int
Основен тип за цели числа. За някои компютри и компилатори има дължина 2 байта, за други - дължина 4 байта. Числата, които може за се запишат в 2 байта са от -216 = -32768 до 216-1 = 32767.
- long
Два пъти "по-дълъг" тип. Минимум 4 байта - следователно съхранява числа  от приблизително -2 милиарда до 2 милиарда).
** Типове за числа с плаваща точка:
- float
Тип за числа с плаваща точка - основен в езика С.
- double
Основен тип за числа с плаваща точка. Числото се пази като двойка цели числа. Например 0.12Е-2 се представя като (12, -2). Тъй като тези две числа се записват в ограничено количество памет (краен брой байтове), то може да възникне проблем с точността. Следващият пример илюстрира този проблем.
// precis.cpp
#include <iostream>
using namespace std;

int main()
{ double o_price = 3E14;
  double d_price = o_price - 0.05;
  double discount = o_price - d_price;
  cout << discount << "\n";
  return 0;
}

0.0625

   Програмата извежда 0.0625 вместо (математически) вярното 0.05. Проблемът е, че числата от тип double имат около 15 значещи цифри в десетичния си запис, а числото, което се записва в променливата d_price, съдържа 16 цифри и се налага закръгляване..



Вход и изход.
    Да се намери стойността (в долари) на купчина американски монети (1 nickel = 5 цента). Броят на монетите от всеки вид се въвежда от клавиатурата.
// coins3.cpp
#include <iostream>
using namespace std;

int main()
{
 cout << "How many pennies do you have? ";
 int pennies;
 cin >> pennies;
 cout << "How many nickels do you have? ";
 int nickels;
 cin >> nickels;
 cout << "How many dimes do you have? ";
 int dimes;
 cin >> dimes;
 cout << "How many quarters do you have? ";
 int quarters;
 cin >> quarters;
/* обща стойност на монетите */
 double total = pennies*0.01 + nickels*0.05 +
                dimes*0.10 + quarters*0.25;
 cout << "Total value = " << total << "\n";
 return 0;
}

How many pennies do you have? 10
How many nickels do you have? 3
How many dimes do you have? 7
How many quarters do you have? 3
Total value = 1.70

* Четене на цели и дробни числа (десетични дроби).
* Грешки при вход - състояния на входния поток: нормално и "грешка".
* Въвеждане на повече от 1 число с един оператор за вход.
cin >> pennies >> nickels >> dimes >> quarters;
 
 

10 3 7 3
10 3 7 3
* Буфериран вход: разделител между въвежданите стойности се нарича "бяло поле" и то е интервал, табулация или нов ред (Enter), като входа се обработва при натискане на клавиша Enter.


Оператор за присвояване.
    Да се намери стойността (в долари) на купчина американски монети. Броят на монетите от всеки вид се въвежда от клавиатурата. Програмата използва само 1 променлива (count) за броя на монетите от различни видове.
// coins4.cpp
#include <iostream>
using namespace std;

int main()
{
 cout << "How many pennies do you have? ";
 int count;

 cin >> count;
/* дефиниция на променливата total*/
 double total = count*0.01;
 cout << "How many nickels do you have? ";
 cin >> count;
/* оператор за присвояване */
/* промяна на стойността на променливата total */
 total = count * 0.05 + total;
 cout << "How many dimes do you have? ";
 cin >> count;
 total = count * 0.10 + total;
 cout << "How many quarters do you have? ";
 cin >> count;
 total = count * 0.25 + total;
 cout << "Total value = " << total << "\n";
 return 0;
}
 

How many pennies do you have? 10
How many nickels do you have? 20
How many dimes do you have? 5
How many quarters do you have? 4
Total value = 2.60

* Текуща стойност на променлива.
    Във всеки момент от изпълнението на програмата променливата count има някаква стойност - текуща стойност на променливата. В случая стойности на променливата са въведените числа 10, 20, 5 и 4.
* Дефиниция на променлива - единствена !
-- с инициализация (със задаване на начална стойност):
  double total = count * 0.01;
-- без инициализация (без задаване на начална стойност):
  int count;
* Оператор за присвояване:

<име на променлива> = <израз>;
  total = count * 0.05 + total;
* Операция "присвояване" - отбелязва се със знака за равенство.
    Има разлики в употребата на знака за равенство в математиката и в С++. В С++ този знак се употребява при задаване на начална стойност на променлива и като операция присвояване.
* Съкращение за операциите добавяне и изваждане на 1:
 month=month+1, съкратено   month++
 month=month-1, съкратено   month--


Грешки при закръгляване.
    Когато работим с числа с плаваща точка, можем да записваме точно само десетичните дроби. Другите числа, например някои прости дроби, се записват приблизително. Ако запишем 1/3 като 0.3333 и умножим това число с 3, получаваме 0.9999, а не 1. В компютъра числата се записват в двоична бройна система и при преобразуването на десетичните дроби в двоична бройна система могат да се появят грешки от закръгляване.
// round1.cpp
#include <iostream>
using namespace std;

int main()
{
 double x = 4.35;
 int n = x*100;
 cout << n << "\n";
 return 0;
}

434

Отпечатва се 434, а не очакваното 435. Вътрешното представяне на числото 4.35 е 4.3499999999 (броят на деветките няма значение). Умножено по 100, дава 434.99999999999. При инициализация на цялата променлива n се извършва неявно преобразуване на типове, като дробната част се отрязва.



Преобразуване на тип.
* Неявно преобразуване на числени типове:
- без загуба на информация (int се преобразува на double):
  double x = 1; int n = 2;
  x = x + n + 3;
- със загуба на информация (double се преобразува на int), компилатора дава предупреждаващо съобщение (warning):
  double x = 4.35;  int n = x*100;
* Явно преобразуване на типове.
    Нека x е променлива от тип double, а е променлива от тип int.
- в езика С++ има специален оператор - static_cast:
  n = static_cast<int>(x);
- в езика С се използва: n = (int)x; или  n = int(x);


Константи (именовани константи).
    В един хладилник има бира - в бутилки и в кутийки. Една бутилка съдържа 2 литра, а една кутийка - 12 унции (oz, 1 oz = 29.586 ml). Да се намери количеството на бирата, ако броят на бутилките и кутийките се задава от клавиатурата.
// volume1.cpp
#include <iostream>
using namespace std;

int main()
{
 double bottles;
 cout << "How many bottles do you have? ";
 cin >> bottles;
 double cans;
 cout << "How many cans do you have? ";
 cin >> cans;
 double total = bottles * 2 + cans * 0.355;
 cout << "The total volume is " << total << "\n";
 return 0;
}

How many bottles do you have? 5
How many cans do you have? 4
Total volume is 11.42

   Какво е значението на числото 0.355? - 1 кутия съдържа 12 унции = 0.355 литра. Вместимостта на 1 бутилка и на 1 кутийка (2 и 0.335 - "магически числа") може да се зададат в програмата като именовани константи (константи, които имат имена).
// volume2.cpp
#include <iostream>
using namespace std;

int main()
{
 double bottles;
 cout << "How many bottles do you have? ";
 cin >> bottles;
 double cans;
 cout << "How many cans do you have? ";
 cin >> cans;
 const double BOTTLE_VOLUME = 2.0;
 const double CAN_VOLUME = 0.355;
 double total = bottles*BOTTLE_VOLUME + cans*CAN_VOLUME;
 cout << "The total volume is " << total << " liter.\n";
 return 0;
}


Аритметични операции в С++.
 

Операция символ тип на аргументите
събиране + a+b int, double
изваждане - a-b int, double
умножение * a*b int, double
деление / a/b int, double, b не е 0
остатък от деление % a%b int, b не е 0

* Приоритети - както в математиката (най-напред се извършват действия *, / и % и след тях + и -)
* Използване на скоби за промяна на реда на изпълнение на аритметичните операции:
(a+b)/2 сборът на числата a и b се дели на 2;
 a+b/2 числото a се събира с половинката на числото b.
* Аргументна зависимост - действието на операцията зависи от типа на аргументите.
- Двата аргумента на аритметичните операции трябва да са от един и същи числов тип данни; резултатът е от същия тип.
- Разрешено е единият от аргументите да е от тип double, а другия - от тип int; тогава аргумента от тип int се преобразува (автоматично) на тип double и след това се извършва аритметичната операция - с аргументи тип double.
- Примери:

операция
+
резултат
1.25+2.0  3.25
1.25+2 3.25
1+2 3
операция
/
резултат
4.1/2.0 2.05
5.0/2 2.5
5/2 2
операция
%
резултат
5%2 1
34%2 0
5.1%2 грешка

* Аритметични функции.
   За да се използват тези функции, трябва да се включи заглавния файл cmath.h с аритметични функции в С++. Това става като се напише
#include <cmath>
 
 
 

Функция  
sin(x) синус
cos(x) косинус
tan(x) тангес
exp(x) експонента
log(x) естествен логаритъм
fabs(x) абсолютна стойност
Функция
floor(x) закръгляване надолу
ceil(x) закръгляване нагоре
sqrt(x) квадратен корен
pow(x,y) x на степен y
asin(x) аркуссинус
atan(x) аркустангес

   Пример - аритметичен израз за намиране на един от корените на квадратно уравнение с коефициенти a, b и c:
(-b+sqrt(b*b-4*a*c))/(2*a)



Комбиниране на  аритметичните операции  с операция присвояване (съставни присвоявания):
+=, -=, *=, /=, %=
   total = total + 0.05 * count;
се записва като
   total += 0.05 * count;
    Операциите за увеличаване и намаляване на стойност на променлива с 1 (++ и --) имат две форми: префиксна и постфиксна. При префиксната форма най-напред се увеличава (или намалява) стойността на променливата и след това се пресмята стойността на аритметичния израз. При постфиксната форма най-напред се пресмята стойността на израза и после се увеличава (или намалява) стойността на променливата.
Пример:
int k = 1;
cout << (++k);
извежда 2, стойността на променливата става 2
int k = 1;
cout << (k++);
извежда 1, стойността на променливата става 2