Advertisement
Guest User

Class16-1

a guest
Sep 18th, 2019
104
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 7.20 KB | None | 0 0
  1. #include <iostream>
  2.  
  3. // Класс обыкновенная дробь
  4. class Fraction {
  5. private:
  6.     unsigned m_num;   // Числитель
  7.     unsigned m_denum; // Знаменатель
  8.     bool m_sign;      // Знак (true - минус, false - плюс)
  9.  
  10.     // Приватный метод для нахождения наибольшего общего делителя (алгоритм евклида)
  11.     // Возвращает наибольший общий делитель
  12.     unsigned getGCD(unsigned a, unsigned b) {
  13.         while (a != b) {
  14.             if (a > b)
  15.                 a = a - b;
  16.             else
  17.                 b = b - a;
  18.         }
  19.  
  20.         return a;
  21.     }
  22.  
  23. public:
  24.     // Конструктор по-умолчанию
  25.     Fraction(): m_num(0), m_denum(1), m_sign(false) {}
  26.  
  27.     // Конструктор, принимает числитель, знаменатель и знак (true значит минус)
  28.     Fraction(unsigned numerator, unsigned denumerator, bool sign = false):
  29.             m_num(numerator), m_denum(denumerator), m_sign(sign)
  30.     {
  31.         if (m_denum == 0) {
  32.             std::cout << "Ошибка! Знаменатель не может быть равен нулю и будет задан значением 1." << std::endl;
  33.             m_denum = 1;
  34.         }
  35.  
  36.         unsigned gcd;
  37.         // Сокращяем числитель и знаменатель
  38.         // Пока наибольший общий делитель числителя и знаменателя не равен 1 -
  39.         // делим их на него и записываем в них же результат этого деления
  40.         while ((gcd = getGCD(m_num, m_denum)) != 1) {
  41.             m_num /= gcd;
  42.             m_denum /= gcd;
  43.         }
  44.     }
  45.  
  46.     // Конструктор из десятичной дроби
  47.     Fraction(double frac) {
  48.         setFromDecimal(frac);
  49.     }
  50.  
  51.     // Метод превращает дробь в обратную (меняет числитель и знаменатель местами)
  52.     void reverse() {
  53.         unsigned tmp = m_num;  // записываем значение числителя во временную переменную tmp
  54.         m_num = m_denum;  // присваеваем числителю значения знаменателя
  55.         m_denum = tmp;    // присваеваем знаменателю значения числителя, сохраненное в переменной tmp
  56.     }
  57.  
  58.     // Метод преобразует обыкновенную дробь в десятичную и возвращает полученное значение в виде числа типа double
  59.     double toDecimal() {
  60.         // Дробь можно преобразовать в конечную десятичную, если знаменатель раскладывается ТОЛЬКО на множители 2 и 5
  61.  
  62.         bool check = true; // Флаг, показывающий, можно ли преобразовать в десятичную дробь
  63.         unsigned denum = m_denum; // Записываем знаменатель в новую переменную для расчетов
  64.  
  65.         // Цикл пока denum больше одного
  66.         while(denum > 1) {
  67.             // Если denum делится на 2 без остатка - делим его на 2 и в него же записываем результат
  68.             if ((denum % 2) == 0) {
  69.                 denum /= 2;
  70.             }
  71.                 // Если denum делится на 5 без остатка - делим его на 5 и в него же записываем результат
  72.             else if ((denum % 5) == 0) {
  73.                 denum /= 5;
  74.             }
  75.                 // Если нет - устанавливаем флаг в false и прерываем цикл
  76.             else {
  77.                 check = false;
  78.                 break;
  79.             }
  80.         }
  81.  
  82.         // Если число нельзя преобразовать в конечную десятичную дробь - выводим предупреждение
  83.         if (!check) {
  84.             std::cout << "Дробь " << m_num << "/" << m_denum << " нельзя преобразовать в конечную десятичную!"
  85.                       << "Будет возвращен приблизительный результат." << std::endl;
  86.         }
  87.  
  88.  
  89.         // Преобразуем m_num в double (т.к. результат деления unsigned/unsigned всегда целочисленный) и делим на знаменатель m_denum
  90.         if (m_sign)
  91.             return -double(m_num) / m_denum;
  92.         else
  93.             return double(m_num) / m_denum;
  94.     }
  95.  
  96.     // Метод устанавливает обыкновенную дробь из десятичной
  97.     void setFromDecimal(double number) {
  98.         m_sign = false;
  99.  
  100.         // Устанавливаем знак, если число отрицательно
  101.         if (number < 0.0) {
  102.             m_sign = true;
  103.             number = -number;
  104.         }
  105.  
  106.         // Знаменатель равен 1
  107.         unsigned denum = 1;
  108.         // Числитель равен десятичной дроби
  109.         double numerator = number;
  110.  
  111.         // Умножаем числитель и знаменатель на 10, пока у числителя есть числа после запятой
  112.         while (numerator - unsigned(numerator) != 0) {
  113.             numerator *= 10;
  114.             denum *= 10;
  115.         }
  116.  
  117.         // Устанавливаем числитель и знаменатель класса
  118.         m_num   = unsigned(numerator);
  119.         m_denum = denum;
  120.  
  121.         unsigned gcd;
  122.         // Пока наибольший общий делитель числителя и знаменателя не равен 1 -
  123.         // делим их на него и записываем в них же результат этого деления
  124.         while ((gcd = getGCD(m_num, m_denum)) != 1) {
  125.             m_num /= gcd;
  126.             m_denum /= gcd;
  127.         }
  128.     }
  129.  
  130.     void print() {
  131.         if (m_sign)
  132.             std::cout << "-";
  133.  
  134.         std::cout << m_num << "/" << m_denum << std::endl;
  135.     }
  136. };
  137.  
  138.  
  139. int main() {
  140.     setlocale(LC_CTYPE, "rus");
  141.  
  142.     // Создаем обыкновенные дроби
  143.     Fraction a(3, 2); // Дробь 3/2
  144.     Fraction b(15, 30, true); // Дробь 1/2
  145.     Fraction c(11, 40); // Дробь 11/40
  146.  
  147.     // Из десятичной дроби
  148.     Fraction d(0.1725); // Дробь 69/400
  149.  
  150.     // Выводим на экран
  151.     std::cout << "Обыкновенные дроби: " << std::endl;
  152.     a.print();
  153.     b.print();
  154.     c.print();
  155.     d.print();
  156.  
  157.     // Выводим на экран в десятичном виде
  158.     std::cout << "В десятичном виде: " << std::endl;
  159.     std::cout << a.toDecimal() << std::endl;
  160.     std::cout << b.toDecimal() << std::endl;
  161.     std::cout << c.toDecimal() << std::endl;
  162.     std::cout << d.toDecimal() << std::endl;
  163.  
  164.     return 0;
  165. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement