Здравствуйте друзья! Хочу вам рассказать об использовании алгоритма Обратной польской записи для создания калькулятора на языке C#.
О самом алгоритме рассказывать не буду, так как такая тема уже поднималась. Заострю внимание на конкретной программе.
Об алгоритме
Алгоритм Обратной польской нотации (ОПН) — форма записи математических выражений, в которой операнды расположены перед знаками операций. Также именуется как обратная польская запись, обратная бесскобочная запись (ОБЗ). © Wikipedia
Наша программа будет состоять из двух частей:
1) Класс RPN (Reverse Polish Notation) — тут будет реализована работа алгоритма
2) Класс Program — тут, собственно, будет реализовано использование класса RPN — писать будем в консоли, что бы было понятнее.
Часть первая: класс RPN
Класс будет содержать ряд методов:
class RPN
{
//Метод Calculate принимает выражение в виде строки и возвращает результат, в своей работе использует другие методы класса
static public double Calculate(string input)
{ ... }
//Метод, преобразующий входную строку с выражением в постфиксную запись
static private string GetExpression(string input)
{ ... }
//Метод, вычисляющий значение выражения, уже преобразованного в постфиксную запись
static private double Counting(string input)
{ ... }
}
Это 3 основных метода класса, опишем их подробнее:
Calculate — метод общедоступный, ему будет передаваться выражение в виде строки, и он будет возвращать результат вычисления. Результат он будет получать используя другие методы.
GetExpression — метод, которому основной метод Calculate будет передавать выражение, и получать его уже в постфиксной записи.
Counting — метод, который получая постфиксную запись выражения будет вычислять его результат.
Так же, помимо 3 основных методов, в классе будет еще 3 метода «обеспечения», это:
IsDelimeter — возвращает true, если проверяемый символ — разделитель
IsOperator — возвращает true, если проверяемый символ — оператор
GetPriority — метод возвращает приоритет проверяемого оператора, нужно для сортировки операторов
Сначала рассмотрим неосновные методы, они простые, так что проблем с пониманием быть не должно:
IsDelimeter
:
//Метод возвращает true, если проверяемый символ - разделитель ("пробел" или "равно")
static private bool IsDelimeter(char c)
{
if ((" =".IndexOf(c) != -1))
return true;
return false;
}
IsOperator
:
//Метод возвращает true, если проверяемый символ - оператор
static private bool IsOperator(char с)
{
if (("+-/*^()".IndexOf(с) != -1))
return true;
return false;
}
GetPriority
:
//Метод возвращает приоритет оператора
static private byte GetPriority(char s)
{
switch (s)
{
case '(': return 0;
case ')': return 1;
case '+': return 2;
case '-': return 3;
case '*': return 4;
case '/': return 4;
case '^': return 5;
default: return 6;
}
}
А теперь основные методы:
Calculate
:
//"Входной" метод класса
static public double Calculate(string input)
{
string output = GetExpression(input); //Преобразовываем выражение в постфиксную запись
double result = Counting(output); //Решаем полученное выражение
return result; //Возвращаем результат
}
GetExpression
:
static private string GetExpression(string input)
{
string output = string.Empty; //Строка для хранения выражения
Stack<char> operStack = new Stack<char>(); //Стек для хранения операторов
for (int i = 0; i < input.Length; i++) //Для каждого символа в входной строке
{
//Разделители пропускаем
if (IsDelimeter(input[i]))
continue; //Переходим к следующему символу
//Если символ - цифра, то считываем все число
if (Char.IsDigit(input[i])) //Если цифра
{
//Читаем до разделителя или оператора, что бы получить число
while (!IsDelimeter(input[i]) && !IsOperator(input[i]))
{
output += input[i]; //Добавляем каждую цифру числа к нашей строке
i++; //Переходим к следующему символу
if (i == input.Length) break; //Если символ - последний, то выходим из цикла
}
output += " "; //Дописываем после числа пробел в строку с выражением
i--; //Возвращаемся на один символ назад, к символу перед разделителем
}
//Если символ - оператор
if (IsOperator(input[i])) //Если оператор
{
if (input[i] == '(') //Если символ - открывающая скобка
operStack.Push(input[i]); //Записываем её в стек
else if (input[i] == ')') //Если символ - закрывающая скобка
{
//Выписываем все операторы до открывающей скобки в строку
char s = operStack.Pop();
while (s != '(')
{
output += s.ToString() + ' ';
s = operStack.Pop();
}
}
else //Если любой другой оператор
{
if (operStack.Count > 0) //Если в стеке есть элементы
if (GetPriority(input[i]) <= GetPriority(operStack.Peek())) //И если приоритет нашего оператора меньше или равен приоритету оператора на вершине стека
output += operStack.Pop().ToString() + " "; //То добавляем последний оператор из стека в строку с выражением
operStack.Push(char.Parse(input[i].ToString())); //Если стек пуст, или же приоритет оператора выше - добавляем операторов на вершину стека
}
}
}
//Когда прошли по всем символам, выкидываем из стека все оставшиеся там операторы в строку
while (operStack.Count > 0)
output += operStack.Pop() + " ";
return output; //Возвращаем выражение в постфиксной записи
}
Counting
:
static private double Counting(string input)
{
double result = 0; //Результат
Stack<double> temp = new Stack<double>(); //Dhtvtyysq стек для решения
for (int i = 0; i < input.Length; i++) //Для каждого символа в строке
{
//Если символ - цифра, то читаем все число и записываем на вершину стека
if (Char.IsDigit(input[i]))
{
string a = string.Empty;
while (!IsDelimeter(input[i]) && !IsOperator(input[i])) //Пока не разделитель
{
a += input[i]; //Добавляем
i++;
if (i == input.Length) break;
}
temp.Push(double.Parse(a)); //Записываем в стек
i--;
}
else if (IsOperator(input[i])) //Если символ - оператор
{
//Берем два последних значения из стека
double a = temp.Pop();
double b = temp.Pop();
switch (input[i]) //И производим над ними действие, согласно оператору
{
case '+': result = b + a; break;
case '-': result = b - a; break;
case '*': result = b * a; break;
case '/': result = b / a; break;
case '^': result = double.Parse(Math.Pow(double.Parse(b.ToString()), double.Parse(a.ToString())).ToString()); break;
}
temp.Push(result); //Результат вычисления записываем обратно в стек
}
}
return temp.Peek(); //Забираем результат всех вычислений из стека и возвращаем его
}
Наш класс готов!
Часть 2: класс Program
Тут все просто, думаю объяснять большого смысла нет, просто прокомментирую:
class Program
{
static void Main(string[] args)
{
while (true) //Бесконечный цикл
{
Console.Write("Введите выражение: "); //Предлагаем ввести выражение
Console.WriteLine(RPN.Calculate(Console.ReadLine())); //Считываем, и выводим результат
}
}
}
Внимание! Ошибки!
Хочу обратить ваше внимание на одну вещь! В нашем классе я не реализовывал проверку входных данных, поэтому при некорректном вводе будут вылетать исключения!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829 830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 |
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Text; using System.Windows.Forms; using System.Globalization; using System.Text.RegularExpressions; using Microsoft.Win32; namespace z1 { //класс "главная форма" public partial class mainForm : Form { private uint iFirstOp, iSecOp, iMemory; //операнды, память private double dFirstOp, dSecOp, dMemory; //операнды, память private bool useDecSepararor, isNewNum; //признаки присутствия десятичной запятой, ввода нового числа private string curOperation, sDecSeparator; //строка с текущей операцией, десятичный разделитель public uint iFO { get { return iFirstOp; } set { iFirstOp = value; } } public uint iSO { get { return iSecOp; } set { iSecOp = value; } } public uint iMem { get { return iMemory; } set { iMemory = value; } } public double dFO { get { return dFirstOp; } set { dFirstOp = value; } } public double dSO { get { return dSecOp; } set { dSecOp = value; } } public double dMem { get { return dMemory; } set { dMemory = value; } } public bool NewNum { get { return isNewNum; } set { isNewNum = value; } } public string CurOp { get { return curOperation; } set { curOperation = value; } } public string sDecSep { get { return sDecSeparator; } set { sDecSeparator = value; } } public bool bDecSep { get { return useDecSepararor; } set { useDecSepararor = value; } } //функция которая выдает различные сообщения если ее аргумент - бесконечность public bool CheckInfinity(double d, char c) { if (double.IsInfinity(d) || double.IsNaN(d)) { switch (c) { //деление на ноль case 'z': MessageBox.Show("Деление на ноль!", "Ошибка!"); break; //выход за рамки типа case 'i': MessageBox.Show("Слишком большое число!", "Ошибка!"); break; } CurOp = "="; opTextBox.Text = CurOp; NewNum = true; bDecSep = false; return true; } else return false; } //конструктор public mainForm() { this.nb1 = new NumButton(this, '1'); this.nb2 = new NumButton(this, '2'); this.nb3 = new NumButton(this, '3'); this.nb9 = new NumButton(this, '9'); this.nb7 = new NumButton(this, '7'); this.nb4 = new NumButton(this, '4'); this.nb6 = new NumButton(this, '6'); [CENTER]14[/CENTER] this.nb8 = new NumButton(this, '8'); this.nb0 = new NumButton(this, '0'); this.nb5 = new NumButton(this, '5'); this.nbNeg = new NumButton(this, 'N'); this.nbComma = new NumButton(this, ','); this.fbPerc = new FuncButton(this, '%'); this.fbMS = new FuncButton(this, 'T'); this.fbSqrt = new FuncButton(this, 'S'); this.fbMC = new FuncButton(this, 'U'); this.fbRes = new FuncButton(this, '='); this.fbMR = new FuncButton(this, 'R'); this.fbAdd = new FuncButton(this, '+'); this.fbDiv = new FuncButton(this, '/'); this.fbInv = new FuncButton(this, 'I'); this.fbSub = new FuncButton(this, '-'); this.nbBs = new NumButton(this, 'W'); this.nbClear = new NumButton(this, 'Q'); this.nbCE = new NumButton(this, 'Z'); this.fbMul = new FuncButton(this, '*'); this.fbMPlus = new FuncButton(this, 'Y'); this.nbD = new NumButton(this, 'D'); this.nbF = new NumButton(this, 'F'); this.nbA = new NumButton(this, 'A'); this.nbC = new NumButton(this, 'C'); this.nbB = new NumButton(this, 'B'); this.nbE = new NumButton(this, 'E'); //процедура инициализации компонентов. описана в mainForm.Designer.cs InitializeComponent(); //переопределение события Click() для NumButton'ов for (int i = 0; i < Controls.Count; i++) { if (Controls[i] is NumButton) { Controls[i].Click += new EventHandler(NumButtonOnClick); } if (Controls[i] is FuncButton) { Controls[i].Click += new EventHandler(FuncButtonOnClick); } } NewNum = true; CurOp = "="; opTextBox.Text = CurOp; dFO = 0.0; dSO = 0.0; dMem = 0.0; iFO = 0; iSO = 0; iMem = 0; memTextBox.Text = ""; workTextBox.Text = "0"; sDecSep = GetDecSep(); bDecSep = false; InvokeOnClick(decRadioButton, EventArgs.Empty); nbComma.Text = sDecSep; } //событие, генерируемое по нажатию кнопки с цифрой, //а точнее тех кнопок, которые модифицируют поле для ввода public void NumButtonOnClick(object sender, EventArgs e) { NumButton nb = (NumButton)sender; if (nb.Enabled) { if (decRadioButton.Checked) { NumButtonEvalDec(nb.Text); } else { NumButtonEvalHex(nb.Text); } } } //событие, генерируемое по нажатию функциональной клавиши public void FuncButtonOnClick(object sender, EventArgs e) { FuncButton fb = (FuncButton)sender; if (fb.Enabled) { if (decRadioButton.Checked) { FuncButtonEvalDec(fb.Text); } else { FuncButtonEvalHex(fb.Text); } } } public string GetDecSep() { string s = NumberFormatInfo.CurrentInfo.NumberDecimalSeparator; //возьмем информацию о десятичном разделителе из реестра. ветка - HCU //string s = (string)Registry.GetValue(@"HKEY_CURRENT_USERControl PanelInternational", "sDecimal", ""); if (s != "") { //MessageBox.Show(s); return s; } else { MessageBox.Show("Не найден ключ с десятичным разделителем в реестре!nБудет использоваться ','" + "nЭто может привести к ошибке!"); return ","; } } //функции, которые вызываются для обработки нажатий по клавишам //если вычисления ведутся с основанием 10 public void NumButtonEvalDec(string but) { switch (but) { //знак "-" // case "/-/": if (workTextBox.Text != "0") { if (!workTextBox.Text.Contains("-")) workTextBox.Text = workTextBox.Text.Insert(0, "-"); else workTextBox.Text = workTextBox.Text.Remove(0, 1); } break; //десятичная запятая case ",": case ".": if (!bDecSep && (!NewNum || workTextBox.Text == "0")) { workTextBox.Text += sDecSep; NewNum = false; bDecSep = true; } break; //бэкспейс case "<--" if (workTextBox.Text != "0") { workTextBox.Text = workTextBox.Text.Remove(workTextBox.Text.Length - 1); if (workTextBox.Text.Length == 0) workTextBox.Text = "0"; } break; //удалить текущее число case "CE": workTextBox.Text = "0"; break; //очистка операндов и поля для ввода case "Clear": NewNum = true; CurOp = "="; opTextBox.Text = CurOp; dFO = 0.0; dSO = 0.0; workTextBox.Text = "0"; NewNum = true; bDecSep = false; break; default: if (workTextBox.Text == "0" || NewNum) { workTextBox.Text = workTextBox.Text.Remove(0); } workTextBox.Text += but; NewNum = false; break; } } public void FuncButtonEvalDec(string func) { //тут те операции, которые должны срабатывать сразу по нажатию соответствующей кнопки: switch (func) { //квадратный корень case "sqrt": dSO = double.Parse(workTextBox.Text); if (!CheckInfinity(dSO, 'i')) { dSO = Math.Sqrt(dSO); workTextBox.Text = dSO.ToString(); dFO = dSO; NewNum = true; bDecSep = false; dSO = 0.0; } else { dSO = 0.0; } return; //обратное число case "1/x": dSO = double.Parse(workTextBox.Text); if (!CheckInfinity(dSO, 'i')) { dSO = 1.0 / dSO; if (!CheckInfinity(dSO, 'z')) { workTextBox.Text = dSO.ToString(); dFO = dSO; CurOp = "="; opTextBox.Text = CurOp; NewNum = true; bDecSep = false; dSO = 0.0; } else { dSO = 0.0; } } else { dSO = 0.0; } return; //процент: вывод такой же как и в калькуляторе Windows, то есть писать надо: //<число> * [+,-,/] <процент> case "%": dSO = double.Parse(workTextBox.Text); if (!CheckInfinity(dSO, 'i')) { dSO = dFO * dSO / 100; if (!CheckInfinity(dSO, 'i')) { workTextBox.Text = dSO.ToString(); NewNum = true; bDecSep = false; dSO = 0.0; } else { dSO = 0.0; } } else { dSO = 0.0; } return; //поместить число в память: case "MS": dMem = double.Parse(workTextBox.Text); if (CheckInfinity(dMem, 'i')) dMem = 0.0; else memTextBox.Text = "M"; return; //прибавить число к хранящемуся в памяти и запомнить результат case "M+": dMem += double.Parse(workTextBox.Text); if (CheckInfinity(dMem, 'i')) dMem = 0.0; else memTextBox.Text = "M"; return; //очистить память case "MC": dMem = 0.0; memTextBox.Text = ""; return; //вывести на экран содержимое памяти case "MR": workTextBox.Text = dMem.ToString(); return; default: break; } //логика такова: есть 2 переменных: first и sec. //ведется учет какая операция была последней: //если "=", то первая переменная вводится заново, если какая-либо из //арифметических операций, то считывается 2я переменная, в нее же заносится результат операции, //а затем результат сохраняется в первой переменной на тот случай, если операции будут идти "цепочкой" switch (CurOp) { case "=": dFO = double.Parse(workTextBox.Text); if (CheckInfinity(dFO, 'i')) dFO = 0.0; break; case "+": dSO = double.Parse(workTextBox.Text); if (!CheckInfinity(dSO, 'i')) { dSO = dSO + dFO; if (!CheckInfinity(dSO, 'i')) { dFO = dSO; } else { dSO = 0.0; } } else { dSO = 0.0; } break; case "-": dSO = double.Parse(workTextBox.Text); if (!CheckInfinity(dSO, 'i')) { dSO = dFO — dSO; if (!CheckInfinity(dSO, 'i')) { dFO = dSO; } else { dSO = 0.0; } } else { dSO = 0.0; } break; case "*": dSO = double.Parse(workTextBox.Text); if (!CheckInfinity(dSO, 'i')) { dSO = dSO * dFO; if (!CheckInfinity(dSO, 'i')) { dFO = dSO; } else { dSO = 0.0; } } else { dSO = 0.0; } break; case "/": dSO = double.Parse(workTextBox.Text); if (!CheckInfinity(dSO, 'i')) { dSO = dFO / dSO; if (!CheckInfinity(dSO, 'z')) { dFO = dSO; } else { dSO = 0.0; } } else { dSO = 0.0; } break; default: break; } CurOp = func; opTextBox.Text = CurOp; workTextBox.Text = workTextBox.Text.Remove(0); workTextBox.Text = dSO.ToString(); NewNum = true; bDecSep = false; dSO = 0; } //функции, которые вызываются для обработки нажатий по клавишам //если вычисления ведутся с основанием 16 public void NumButtonEvalHex(string but) { switch (but) { //бэкспейс case "<--": if (workTextBox.Text != "0") { workTextBox.Text = workTextBox.Text.Remove(workTextBox.Text.Length - 1); if (workTextBox.Text.Length == 0) workTextBox.Text = "0"; } break; //удалить текущее число case "CE": workTextBox.Text = "0"; break; //очистка операндов и поля для ввода case "Clear": NewNum = true; CurOp = "="; opTextBox.Text = CurOp; iFO = 0; iSO = 0; workTextBox.Text = "0"; NewNum = true; break; default: if (workTextBox.Text == "0" || NewNum) { workTextBox.Text = workTextBox.Text.Remove(0); } workTextBox.Text += but; NewNum = false; break; } } public void FuncButtonEvalHex(string func) { //тут те операции, которые должны срабатывать сразу по нажатию соответствующей кнопки: switch (func) { //поместить число в память: case "MS": try { iMem = uint.Parse(workTextBox.Text, NumberStyles.AllowHexSpecifier); memTextBox.Text = "M"; } catch (OverflowException) { MessageBox.Show("Слишком большое число!", "Ошибка!"); } return; //прибавить число к хранящемуся в памяти и запомнить результат case "M+": try { iMem += uint.Parse(workTextBox.Text, NumberStyles.AllowHexSpecifier); memTextBox.Text = "M"; } catch (OverflowException) { MessageBox.Show("Слишком большое число!", "Ошибка!"); } return; //очистить память case "MC": iMem = 0; return; //вывести на экран содержимое памяти case "MR": workTextBox.Text = String.Format("{0:X}", iMem); return; default: break; } //логика такова: есть 2 переменных: first и sec. //ведется учет какая операция была последней: //если "=", то первая переменная вводится заново, если какая-либо из //арифметических операций, то считывается 2я переменная, в нее же заносится результат операции, //а затем результат сохраняется в первой переменной на тот случай, если операции будут идти "цепочкой" switch (CurOp) { case "=": try { iFO = uint.Parse(workTextBox.Text, NumberStyles.AllowHexSpecifier); } catch (OverflowException) { MessageBox.Show("Слишком большое число!", "Ошибка!"); } break; case "+": try { iSO = uint.Parse(workTextBox.Text, NumberStyles.AllowHexSpecifier); iSO = iSO + iFO; iFO = iSO; } catch (OverflowException) { MessageBox.Show("Слишком большое число!", "Ошибка!"); } break; case "-": try { iSO = uint.Parse(workTextBox.Text, NumberStyles.AllowHexSpecifier); if (iSO > iFO) { MessageBox.Show("Отрицательный результат!"); InvokeOnClick(nbClear, EventArgs.Empty); } else { iSO = iFO - iSO; iFO = iSO; } } catch (OverflowException) { MessageBox.Show("Слишком большое число!", "Ошибка!"); } break; case "*": try { iSO = uint.Parse(workTextBox.Text, NumberStyles.AllowHexSpecifier); iSO = iSO * iFO; iFO = iSO; } catch (OverflowException) { MessageBox.Show("Слишком большое число!", "Ошибка!"); } break; case "/": try { iSO = uint.Parse(workTextBox.Text, NumberStyles.AllowHexSpecifier); iSO = iFO / iSO; dFO = dSO; } catch (OverflowException) { MessageBox.Show("Слишком большое число!", "Ошибка!"); } catch (DivideByZeroException) { MessageBox.Show("Деление на ноль!", "Ошибка!"); } break; default: break; } CurOp = func; opTextBox.Text = CurOp; workTextBox.Text = workTextBox.Text.Remove(0); [CENTER]33[/CENTER] workTextBox.Text = String.Format("{0:X}", iSO); NewNum = true; bDecSep = false; iSO = 0; } //обработчики событий для кликов по радиокнопкам //отключение ненужных кнопок и обнуление переменных private void decRadioButton_Click(object sender, EventArgs e) { NewNum = true; CurOp = "="; opTextBox.Text = CurOp; dFO = 0.0; dSO = 0.0; iFO = 0; iSO = 0; iMem = 0; dMem = 0.0; memTextBox.Text = ""; workTextBox.Text = "0"; NewNum = true; bDecSep = false; nbComma.Enabled = true; nbA.Enabled = false; nbB.Enabled = false; nbC.Enabled = false; nbD.Enabled = false; nbE.Enabled = false; nbF.Enabled = false; fbSqrt.Enabled = true; fbInv.Enabled = true; fbPerc.Enabled = true; nbNeg.Enabled = true; } private void hexRadioButton_Click(object sender, EventArgs e) { NewNum = true; CurOp = "="; opTextBox.Text = CurOp; iFO = 0; iSO = 0; dFO = 0.0; dSO = 0.0; iMem = 0; dMem = 0.0; memTextBox.Text = ""; workTextBox.Text = "0"; NewNum = true; bDecSep = false; nbComma.Enabled = false; nbA.Enabled = true; nbB.Enabled = true; nbC.Enabled = true; nbD.Enabled = true; nbE.Enabled = true; nbF.Enabled = true; fbSqrt.Enabled = false; fbInv.Enabled = false; fbPerc.Enabled = false; nbNeg.Enabled = false; } //обработчик назатий клавиш клавиатуры private void workTextBox_KeyPress(object sender, KeyPressEventArgs e) { char key = Char.ToUpper(e.KeyChar); //клавиша ввода - это еще и '=' if (key == (char)Keys.Enter) { key = '='; } //а точка вполне может быть десятичным разделителем if (key == '.') { key = ','; } for (int i = 0; i < Controls.Count; i++ ) { if (Controls[i] is NumButton) { NumButton nb = (NumButton)Controls[i]; if (key == nb.chKey) { InvokeOnClick(nb, EventArgs.Empty); } } if (Controls[i] is FuncButton) { FuncButton fb = (FuncButton)Controls[i]; if (key == fb.chKey) { InvokeOnClick(fb, EventArgs.Empty); } } } } private void evSysGroupBox_Validated(object sender, EventArgs e) { workTextBox.Focus(); } //показать форму с информацией о программе private void aboutToolStripMenuItem_Click(object sender, EventArgs e) { af = new aboutForm(); af.Show(); } //копирование в буфер обмена private void copyToolStripMenuItem_Click(object sender, EventArgs e) { Clipboard.SetDataObject(workTextBox.Text); } //вставка из буфера обмена private void pasteToolStripMenuItem_Click(object sender, EventArgs e) { IDataObject iData = Clipboard.GetDataObject(); if (iData.GetDataPresent(DataFormats.Text)) { string data = (String)iData.GetData(DataFormats.Text); /* if ((decRadioButton.Checked && !Regex.Match(data, @"^-?d+" + GetDecSep() + @"?d*[Ee]?-?d+$").Success) || (hexRadioButton.Checked && !Regex.Match(data,@"^[A-Fa-fd]+$").Success)) { MessageBox.Show("В буфере не число!!"); } else { workTextBox.Text = data; } */ if (decRadioButton.Checked) { try { double.Parse(data); workTextBox.Text = data; } catch (FormatException) { MessageBox.Show("В буфере не число!!"); } } else { try { int.Parse(data, NumberStyles.AllowHexSpecifier); workTextBox.Text = data; } catch (FormatException) { MessageBox.Show("В буфере не число!!"); } } } } //вырезать в буфер обмена private void cutToolStripMenuItem_Click(object sender, EventArgs e) { Clipboard.SetDataObject(workTextBox.Text); workTextBox.Text = "0"; } } //класс "кнопка с цифрой" public class NumButton : Button { private char chHotKey; public char chKey { get { return chHotKey; } set { chHotKey = value; } } public NumButton(Control parent, char key) : base() { Parent = parent; chKey = key; SetStyle(ControlStyles.Selectable, false); } } public class FuncButton : Button { private char chHotKey; public char chKey { get { return chHotKey; } set { chHotKey = value; } } public FuncButton(Control parent, char key) : base() { Parent = parent; chKey = key; SetStyle(ControlStyles.Selectable, false); } } [CENTER]}[/CENTER] |
На чтение 10 мин Просмотров 38 Опубликовано 10 апреля 2023 Обновлено 10 апреля 2023
Содержание
- Онлайн-конструктор блок-схем
- 7 онлайн-сервисов для создания блок-схем
- Lucidchart
- draw.io
- Cacoo
- Gliffy
- Wireflow
- Textographo
- Google Drawings
- Как создавать блок-схемы алгоритмов и диаграмм: топ-6 бесплатных онлайн-сервисов?
- Что такое «блок-схема»?
- Сервисы для создания алгоритмов (блок-схем)
- draw.io.
- Lucidchart
- Google Drawings
- Wireflow
- Gliffy
- Cacoo
- Заключение
Онлайн-конструктор блок-схем
Здесь можно сконструировать онлайн блок схему. Для этого надо ввести код в поле ввода, приведенное ниже. Сразу описываются структурные блоки, а затем связи между ними. После ввода — нажать кнопку «Рисовать». Сейчас введен код примера блок-схемы, которую Вы видите ниже.
Airlines.push_back(«1.Айрофлот»);
Airlines.push_back(«2.Айрофлот»);
Airlines.push_back(«3.Айрофлот»);
std::cout >& tickets,const std::list & Airlines)<
int c = 0;
for (auto i = tickets.begin(); i != tickets.end(); ++i)
<
int g = 0;
for (auto k = Airlines.begin(); k != Airlines.end(); ++k)
<
if (c == g) cout le = *i;
for (auto j = le.begin(); j != le.end(); ++j)
cout tickets= < <>,<>,<> >;
Airlines = AirlinesList();
do <
c = 0;
std::cout > ans;
if (ans == ‘Y’ || ans == ‘y’) <
std::cout > N;
std::cout > count;
for (auto i = tickets.begin(); i != tickets.end(); i++) <
>
else if (ans != ‘N’ && ans != ‘N’) <
cout
int minutes(int h, int m)
<
return h * 60 + m;
>
int main()
<
int a, b, c, d, n, m;
cin >> a >> b >> c >> d >> n >> m;
int minutes_ab = minutes(a, b);
int minutes_cd = minutes(c, d);
int minutes_nm = minutes(n, m);
cout
#include
#include
using namespace std;
int main() <
int min,i,j;
const int row=5;
const int col=5;
int mr[row][col];
srand(time(NULL));
for(int i=0; i =j&&min>mr[i][j]) <
min=mr[i][j];
Источник
7 онлайн-сервисов для создания блок-схем
Работу с блок-схемами, скорее всего, нельзя считать развлечением, но нельзя отрицать, что они невероятно полезны. С их помощью сложные процессы можно разбить на множество мелких и тогда они уже не будут казаться такими сложными.
Хотя существуют отличные программы для построения блок-схем для Windows и других платформ. Вы даже можете создавать их в Excel или Microsoft Word. Но лучше всего использовать специализированные онлайн-сервисы.
Lucidchart
Lucidchart является самым популярным онлайн-сервисом для построения блок-схем. Удобный интерфейс позволяет легко создавать блок-схемы и управлять ими. На выбор есть готовые шаблоны, но можно начать работу и с чистого листа.
Так как это довольно мощный инструмент он имеет бесплатный и 3 платных тарифных плана — 6 долларов для продвинутого домашнего использования, 9 долларов за профессиональную версию и 20 долларов для команды.
Если вы пользуетесь бесплатной учетной записью, вы получаете только 25 Мб памяти и до пяти документов. Платные тарифы предоставляют больше возможностей, например: больший размер хранилища, неограниченное количество форм и документов, связывание данных, импорт в Microsoft Visio и многое другое.
Но даже бесплатная учетная запись дает доступ к основным формам, стрелкам и текстовым полям. Этого будет достаточно в большинстве случаев. Для бесплатного тарифа также доступна возможность совместной работы. Но есть некоторые ограничения. Например, представитель какой-либо команды может сотрудничать с бесплатным пользователем, но бесплатный пользователь может редактировать схему только в том случае, если в ней менее 60 объектов и если в ней нет никаких объектов платного уровня.
Lucidchart поддерживает форматы JPEG, PDF, PNG, SVG и Visio (VDX). Существует даже поддержка импорта из Amazon Web Service (AWS), Visio (VSDX), Omnigraffle и многих других сервисов. Если вам нужно закончить блок-схему позже, все ваши данные будут храниться в их облаке, так что в следующий раз вы просто продолжите с того места, где остановились.
draw.io
Сервис draw.io подойдет для тех, кто ищет бесплатное решение для построения блок-схем. На этом сайте даже не нужно регистрироваться. Можно создать новую блок-схему с нуля или использовать готовый шаблон (их несколько десятков). Работать с draw.io довольно просто. Вы можете добавлять нужные фигуры, стрелки и другие объекты из бокового меню.
Все, что вам нужно сделать, чтобы начать работу, это один раз выбрать место для сохранения файлов, которое в дальнейшем запоминается и используется по умолчанию. Можно выбрать отдельную папку в Google Drive, Dropbox, OneDrive (сервис будет иметь доступ только к указанной папке) или место на жестком диске компьютера. Если вам нужно работать с другими людьми, Google Drive будет лучшим вариантом.
Сервис draw.io поддерживает импорт файлов формата JPEG, PNG, SVG, сторонних сервисов Gliffy, Lucidchart и VSDX. Диаграммы, которые вы создаете можно экспортировать в HTML, JPEG, PDF, PNG, SVG и XML.
Cacoo
Если совместная работа в реальном времени является для вас обязательным требованием, то обратите внимание на сервис Cacoo. Он имеет множество шаблонов для проекта, будь то блок-схемы, модели или диаграммы. Cacoo имеет широкий выбор форм на выбор, независимо от типа проекта.
Лучшая особенность Cacoo — это возможность совместной работы в режиме реального времени. Несколько человек в вашей команде могут работать над блок-схемой одновременно. Кроме того, есть функция чата, так что вы можете видеть и комментировать изменения. Поскольку процесс работы может немного усложниться, когда несколько человек работают над одним документом одновременно, Cacoo предоставляет поля для заметок, чтобы вы могли отслеживать, кто участвует в изменениях.
Cacoo также отлично подходит для одиночных пользователей, так как вы получаете хранилище для 1000 листов, неограниченный общий доступ, импорт и экспорт в SVG.
Цены на Cacoo достаточно доступны. Тариф для команды из 3 человек начинается с $18 в месяц. Корпоративный тариф позволяет установить Cacoo на собственном сервере, стоимость такого варианта начинается с 600 долларов в год для 10 пользователей. Все тарифы имеют 14-дневный бесплатной пробный период.
Gliffy
Если вам нужен простой инструмент для работы, то обратите внимание на сервис Gliffy. По сравнению с другими службами, Gliffy немного более схематичный. Это хороший вариант, когда вам нужно быстро построить блок-схему. Вы сможете создать хороший вариант всего за несколько кликов.
Есть встроенные базовые шаблоны, которые позволяют начать еще быстрей. Однако, когда вы начинаете настраивать свои блок-схемы, процесс редактирования уже не так прост, как, например, в Lucidchart. Есть несколько особенностей интерфейса, которые могут немного раздражать.
Gliffy предоставляет возможность поделиться и даже пригласить других людей просматривать, редактировать или оставлять комментарии. Но эти инструменты для совместной работы не такие эффективные, как у других сервисов. Gliffy предлагает тарифы, начинающиеся с $8 в месяц для обычных пользователей, и командный тариф за 60 долларов в год.
Wireflow
Wireflow — еще один бесплатный сервис. Он лучше всего подойдет для веб-разработчиков и дизайнеров приложений. Симпатичный интерфейс предлагает множество иконок, которые вы можете перетащить на чистый лист и выстроить связь между ними.
Есть много стрелок и соединительных элементов на выбор, ими можно управлять с помощью перетаскивания. Когда вы закончите создавать свою диаграмму, вы можете экспортировать ее в формат JPG. Это самый большой недостаток Wireflow, так как вы не можете выбрать другой формат.
С другой стороны, сервис бесплатен, без каких-либо вариантов платных тарифов, так что это ожидаемо. Если все, что вам нужно, — это создать блок-схемы для демонстрации взаимодействия пользователей с ПО, то Wireflow отлично справится с этой задачей.
Textographo
Вам нужно создавать блок-схемы, но вы не хотите иметь дело с утомительной работой по размещению и изменению формы объектов и стрелок? Тогда попробуйте Textographo. Это уникальный сервис, который использует текстовые команды для создания блоков и связей между ними. Программистам он явно понравится.
Все, что нужно сделать пользователю, — это ввести свою диаграмму в определенную текстовую форму, которая использует хештеги, ключевые слова и разметку. Textographo берет этот текст и превращает его в статические или анимированные диаграммы, которые используются в блок-схемах, ментальных картах и деревьях решения.
Как только вы разложите текст, Textographo автоматически приступит к работе и организует все в виде диаграммы. Поскольку Textographo сохраняет все документы в своем облаке, вы можете работать вместе со своей командой, приглашая ее просматривать, давать обратную связь и делиться идеями.
Существует два уровня учетной записи: Essentials и Premium. Уровень Essentials начинается с 8 долларов в месяц, если вы платите сразу за год, или 12 долларов в месяц. Премиум-версия стоит $19 в месяц.
Google Drawings
Если вы имеете учетную запись Google, то у вас уже есть доступ к сервису Google Drawings. Чтобы начать в нем работать нужно сначала открыть свой Google Диск, а затем нажать кнопку «Создать» и выбрать Google Drawings.
Все формы можно перемещать при помощи простого перетаскивания, а также изменять размер и поворачивать при необходимости. А поскольку Google Drawings работает через Google Drive, совместное использование не является проблемой. Просто пригласите участников вашей команды по электронной почте и дайте им разрешение на просмотр, редактирование или комментирование.
Вы сможете экспортировать блок-схему в виде файла изображения или SVG или опубликовать ее в интернете. Google Drawings можно использовать бесплатно, так как он находится в вашем аккаунте Google, где вы получаете 15 ГБ бесплатного хранилища для всех приложений Google.
Источник
Как создавать блок-схемы алгоритмов и диаграмм: топ-6 бесплатных онлайн-сервисов?
Производители софта разного уровня предлагают приложения, с помощью которых можно удобно строить блок-схемы. Однако, когда не хочется занимать память на компьютере, можно воспользоваться онлайн-сервисами. Они работают не хуже приложений, и большинство из них бесплатны.
Что такое «блок-схема»?
Правильнее будет сказать, что это «схема алгоритма». Она позволяет понять последовательность того или иного действия. Это помогает решать множество задач, включая рационализацию работы коллектива и планирование свободного времени.
- Необходимо ввести изначальные данные.
- Данные, с которыми ведется работа, должны быть различными (общность).
- Последовательность шагов.
- Однозначность трактовки.
- Корректность.
- Минимальное время для решения задачи.
- Результат, прямо зависящий от исходных данных.
Сервисы для создания алгоритмов (блок-схем)
draw.io.
Сервис абсолютно бесплатный и даже не требует регистрации. Перед началом работы нужно лишь указать директорию, в которой будут сохраняться полученные результаты. Рекомендуется использовать хранилище Google Drive, потому что оно поддерживает функцию совместных проектов.
- Создание собственной схемы или использование шаблонов (которых всего 5).
- Понятный интерфейс: для создания схем нужно перетягивать выбранные элементы с боковой панели.
- Импорт файлов в различных форматах (JPEG, PNG и др.).
- Созданные файлы сохраняются с расширениями HTML, JPEG, PDF, и др.
Фото: Онлайн-сервис draw.io.
Конечно, по функционалу этот сервис уступает многим платным. Но в нем достаточно инструментов для создания понятных блок-схем.
Lucidchart
Это платный сервис, но в нем присутствует возможность бесплатной версии с ограниченными возможностями. Тем не менее в ограниченной версии пользователям доступны базовые элементы и даже возможность совместных проектов.
- Возможность сохранять полученные документы в нескольких форматах.
- Импорт файлов с других сервисов.
- Возможность поставить работу на «паузу» и сохранить промежуточный результат в облачном хранилище.
Понравилась статья? Подпишись на наш телеграм канал . Там новости выходят быстрее!
Google Drawings
Если вы владелец аккаунта на Гугл, то для вас доступна возможность бесплатно пользоваться Google Drawings.
- Добавление собственных элементов.
- Менять размер элементов.
- Коллективные проекты с привязкой с гугл-диску.
- Возможность делиться полученными результатами в сети.
- Экспорт полученных результатов в виде графических фалов или в формате SVG.
- Хранилище на 15 Гб с возможностью покупки дополнительного места.
Wireflow
Этот сайт абсолютно бесплатный. Прекрасно подходит для веб-дизайнеров и разработчиков приложений.
- Понятный интуитивный интерфейс.
- Шаблоны и дополнительные элементы.
- Экспорт полученного файла в формате JPG.
Gliffy
Легкий и доступный инструмент, но с ограниченным функционалом. Он платный, однако присутствует бесплатная пробная версия на две недели.
- Базовые шаблоны.
- Дополнительные элементы.
- Возможность работы оффлайн.
- Коллективные проекты.
Cacoo
Это платная платформа, но, как и в Gliffy, здесь присутствует возможность бесплатного двухнедельного тестирования.
- Приятный и понятный интерфейс.
- Чат.
- Совместная работа.
- Множество шаблонов, каркасов и др.
- Показывает всех, кто работает над проектом в данный момент.
Заключение
Блок-схемы – отличный вариант для визуального мозгового штурма. Для их создания не обязательно устанавливать специальный софт.
Источник
Исполнитель Калькулятор 2 Алгоритмы Алгоритм – это четко определенный план действий для исполнителя. Свойства алгоритма • дискретность: состоит из отдельных шагов (команд) • понятность: должен включать только команды, известные исполнителю (входящие в СКИ) • определенность: при одинаковых исходных данных всегда выдает один и тот же результат • конечность: заканчивается за конечное число шагов • массовость: может применяться многократно при различных исходных данных • корректность: дает верное решение при любых допустимых исходных данных К. Поляков, 2010 -2013 http: //kpolyakov. spb. ru
Представление алгоритмов: Письменное алг открывание двери нач Графическое начало взять ключ вставить ключ в замок повернуть ключ 2 раза по часовой стрелке открыть дверь Взять ключ Вставить ключ в замок Повернуть ключ 2 раза по часовой стрелке Открыть дверь Кон конец
Исполнители алгоритма: • • • Робот-Удвоитель Робот-Калькулятор Робот-Чертежник Человек Компьютер
Исполнитель Калькулятор 5 Удвоитель Исполнитель Удвоитель работает с одним числом и умеет выполнять с ним две операции (команды): 1. прибавь 1 2. умножь на 2 Программа – это последовательность номеров команд, которые нужно выполнить. Программа 12211 2 начальное число К. Поляков, 2010 -2013 1 3 2 6 2 12 1 13 1 14 результат http: //kpolyakov. spb. ru
Исполнитель Калькулятор 6 составление программы Используя команды: 1. прибавь 1 2. умножь на 2 написать программу, которая из 3 получает 13. 3 8 16 9 7 8 10 6 14 5 6 4 1 13 12 дерево вариантов 2 24 3 4 1 5 2 8 1 2 1 6 10 9 16 8 К. Поляков, 2010 -2013 6 Ответ: 221 1 7 2 2 1 14 12 13 http: //kpolyakov. spb. ru 2 24
Исполнитель Калькулятор 7 Обратная задача (решение «с конца» ) 13 нельзя делить на 2! 1 1 Ответ: 221 12 ! 9 5 29 27 3 2 6 1 10 9 7 33 11 15 21 11 1 13 45 17 2 5 3 ? Почему решение «с конца» короче? Решение «с конца» короче, если в списке команд есть необратимая операция (каждое целое число можно умножить на 2, но не каждое делится на 2)! К. Поляков, 2010 -2013 http: //kpolyakov. spb. ru 81
Исполнитель Калькулятор 8 Удвоитель У исполнителя есть команды: 1. прибавь 1 2. умножь на 2 Задания: 1) Какие числа можно получить из 0? 2) Как из числа 5 получить 105? 3)Как построить самую короткую программу для получения заданного числа N из 0? К. Поляков, 2010 -2013 http: //kpolyakov. spb. ru
Исполнитель Калькулятор 9 Исполнитель Калькулятор Используя команды: 1. прибавь 2 2. умножь на 3 написать программу, которая из 3 получает 29. 13 45 17 15 21 9 7 9 5 3 33 11 29 27 1 81 дерево вариантов 2 3 5 1 7 2 15 1 2 1 9 21 17 45 13 К. Поляков, 2010 -2013 9 Ответ: 221 1 11 2 2 1 33 27 29 http: //kpolyakov. spb. ru 2 81
Исполнитель Калькулятор 10 Обратная задача (решение «с конца» ) 29 1 1 Ответ: 221 27 ! 11 15 21 7 33 9 5 3 9 1 23 45 17 9 2 25 1 13 нельзя делить на 3! 2 7 3 ? Почему решение «с конца» короче? Решение «с конца» короче, если в списке команд есть необратимая операция (каждое целое число можно умножить на 3, но не каждое делится на 3)! К. Поляков, 2010 -2013 http: //kpolyakov. spb. ru 29 27 81
Для создания любой программы нужно определить границы решаемой задачи. По этому определим для работы нашей программы седеющий круг задач.
Описание работы простого калькулятора:
Описание алгоритма на естественном языке
1) Пользователь вводит 1 число сохраняем его в переменную A 2) Пользователь вводит действие в виде символов + (сложение) – (вычитание) * (умножение) / (деление) 3) Запоминаем команду в строковую переменную Moushen (действие) 4) Пользователь вводит 2 число сохраняем его в переменную B 5) Проверяем какое действие выполнить на основе выбора пользователя Если Moushen=сложение то выполняем C=A+B Если Moushen=вычитание то выполняем C=A-B Если Moushen=умножение то выполняем C=A*B Если Moushen=деление то выполняем проверку можем ли мы делить вообще: Если B = 0 выводим сообщение об ошибке Если B <>0 то производим деление C=A/B 6) Выводим результат операции на экран. 7) Спрашиваем закончил пользователь или нет если да то выходим из программы если нет то считаем следующее число |
Блок схема |
Для создания простого калькулятора воспользуемся стандартным консольным приложением в котором будем спрашивать пользователя и выводить ему результат работы на экран.
Для этого запустим Embarcadero Rad Studio XE 3
Создаем новый консольный проект для этого выполняем следующие действия.
Выбираем пункт меню File -> New -> Other… | Далее выбираем язык программирования и ярлык консольного приложения
|
В мастере создания проекта просто нажимаем OK |
Создается шаблон проекта все что написала среда разработки нужно оставлять так как есть
Для того чтобы вывести сообщение пользователю нужно как то вывести данные в консоль для этого подключим библиотеку Iostream.h на нашему проекту.
После отключения нам станут доступны следующие функции.
1) Функция вывода данных в консоль
cout (console out – консольный вывод) – данная функция позволяет вывести содержимое любой переменной на экран консоли
пример 1 :
Выводим на экран содержимое переменной а
пример 2 :
Выводим на экран текст например слово privet
пример 3 :
когда нужно перенести текст на новую строчку нужно вывести на экран символ переноса строки n
2) Функция получения данных с клавиатуры:
cin (console input – консольный ввод) – данная функция позволяет записать из клавиатуры значение переменной
Пример 1:
Запись числа в переменную а и вывод его на экран
пример 2 :
Ввод пользователем символа клавиатуры и вывод его на экран
пример 3 :
Ввод нескольких символов с клавиатуры и вывод их на экран, особенность данного подхода в том что символы вводить нужно без пробела так как cin читает данные до пробела.
Задание:
Реализовать консольный калькулятор.
Решение.
1) Объявляем переменные которые понадобятся для калькулятора
2) Получаем 1 число от пользователя
3) Получаем действие от пользователя
4) Получаем второе число
5) На основе выбора пользователя выполняем операцию с переменными
6) Все считается ура
Дополнительные задания:
1) Решить вопрос с дробными делением чисел в калькуляторе.
2) В конце расчетов калькулятор должен спрашивать закончил ли пользователь вычисления если нет то начать работу калькулятора заново.
3) Решить вопрос с делением на 0.