close

Вход

Забыли?

вход по аккаунту

4. Программирование вычислительных процессов

код для вставкиСкачать
4. Программирование вычислительных процессов. Управляющие операторы C#
Решение задачи на ЭВМ – это сложный процесс, в ходе которого пользователю приходится
выполнять целый ряд действий, прежде чем он получит интересующий его результат.
Для описания приложений, написанных на объектно-ориентированном языке
программирования применяются различные диараммы (классов, сценариев использования,
взаимодействия, последовательности действий, свзяей, состояний, деятельности, выполнения,
компонентов, размещения). Основнвми еденицами этих диаграмм являются классы и их
взаимосвязи. А для описания работы конкретных методов конкретных классов применяется, как
правило, словестное описание.
Но поскольку вы делаете первые шаги в программировании, то для наглядности описания
применения управляющих операторов C#, при ришении тех или иных задач, будем использовать
алгоритмы.
Алгоритмизация – это процесс проектирования алгоритма, то есть выделение совокупности
действий, используемых в математическом методе, и сведения их к совокупности действий,
которые будет выполнять ЭВМ.
Алгоритм – совокупность точно описанных действий, приводящих от исходных данных к
желаемому результату и удовлетворяющих следующим свойствам:
- определенности – алгоритм должен однозначно, точно и понятно задавать выполняемые
действия (для одних и тех же исходных данных должен получаться один и тот же результат);
- дискретности – алгоритм должен представлять действие в виде последовательности
составных частей;
- результативности – алгоритм должен приводить к желаемому точному результату за
конечное время;
- массовости – алгоритм должен быть приемлем для решения всех задач определенного
класса.
Существуют различные способы записи алгоритмов (словесный, формульно-словесный,
графический, аналитический). Каждый из способов имеет свои плюсы и минусы; В данном курсе в
основном используется два способа графического представления алгоритма: блок-схема и
словесное описание.
Блок-схемы – это графическое представление алгоритма, дополняемое словесными
записями. Каждый блок алгоритма отображается геометрической фигурой (блоком). Правила
выполнения схем алгоритмов регламентируют ГОСТ 19.701-90. Графические фигуры соединяются
линиями, потоками информации. Эти линии задают порядок переходов от блока к блоку. Блоксхемы наглядны для представления простых вычислительных алгоритмов и ориентированы для
программирования задач на языках АССЕМБЛЕР, АЛГОЛ, БЕЙСИК, ФОРТРАН, ПЛ.
Для крупных программ, рисуются укрупненные блоки алгоритма, которые потом
уточняются. Этот процесс продолжается до тех пор, пока каждый алгоритмический блок не станет
однозначно отражать одну или несколько языковых конструкций выбранного разработчиком
языка программирования.
Поэтому для пояснения работы этих и некоторых других операторов будем использовать
блок-схемы как алгоритмы нижнего уровня. А для объяснения вычислительных процессов
решения сложных задач, в том числе численных методов, используем словесное описание.
4.1. Линейные процессы вычислений
Простейший алгоритм представляет собой цепочку блоков (операторов) от начального блока
до конечного. Каждый блок должен быть выполнен один единственный раз. Это линейный
алгоритм. Он отражает линейный вычислительный процесс. Основой линейных процессов
является последовательность операторов, обеспечивающих ввод исходных данных, вычисление
выражений и возврат результатов вычислений (либо в вызываемый метод, либо на экран, пчать, в
файл и т.п.).
4.1.1. Консольный ввод
В классе Console определены несколько методов, считывающих стандартный входной поток:
System.Console.Read() – читает следующий символ из стандартного входного потока.
System.Console.ReadLine() – считывает следующую строку символов из стандартного
входного потока.
System.Console.ReadLine()
Метод считывает строку – последовательность символов, за которыми следует символ
возврата каретки (шестнадцатеричное значение 0x000d), символ перевода строки
(шестнадцатеричное значение 0x000a). Значение, возвращаемое методом, имеет тип string
(строковый тип данных рассматривается позже). В следующей части программы считывается
строка и записывается в строковую переменную str:
string str;
str = System.Console.ReadLine();
Как только программа встречает вызов метода System.Console.ReadLine(), её выполнение
приостанавливается, и выводится моргающий курсор – признак ожидания ввода данных
пользователем. Окончанием ввода пользовательских данных является нажатие клавиши <enter>.
После этого метод возращает введенные данные, которые записываются в строковую переменную str.
System.Console.Read()
Метод считывает символ из входного потока. В качестве значения он возвращяет целое
число (типа int) – номер символа в кодовой таблице или -1, если символа во входном потоке нет
(например, если пользователь нажал кдавишу <enter>):
int u_ch;
char ch;
u_ch = System.Console.Read();
System.Console.ReadLine();
ch = (char) u_ch;
Поскольку нам требуется не int, а char, а неявного преобразования от int к char не
существует, приходится применить операцию явного преобразования типа. Оператор 3 считывает
остаток строки и никуда его не передает. Это необходимо потому, что ввод данных выполняется
через буфер – специальную область оперативной памяти. Фактически данные сначала заносятся в
буфер, а затем считываются оттуда процедурами ввода. Занесение в буфер выполняется по
нажатию клавиши Enter вместе с ее кодом. Метод Read(), в отличие от ReadLine(), не очищает
буфер, поэтому следующий после него ввод будет выполняться с того места, на котором
закончился предыдущий.
Ввод чисел
В классе Console определены методы ввода строки и отдельного символа, но нет методов,
которые позволяют непосредственно считывать с клавиатуры числа. Ввод числовых данных
выполняется в два этапа:
1. Символы, представляющие собой число, вводятся с клавиатуры в строковую переменную
(в данном случае выполняющую роль буфера – временного хранилища).
2. Выполняется преобразование из строки в переменную соответствующего типа.
Преобразование можно выполнить либо с помощью специального класса Convert,
определенного в пространстве имен System, либо с помощью метода Parse, имеющегося в каждом
стандартном арифметическом классе.
Рассмотрим пример ввода чисел:
namespace ConsoleApplication1
{
class ConsoleInput
{
static void Main()
{
// строка – буфер для ввода чисел
string buf;
// Ввод целого числа
Console.WriteLine("Введите целое число");
buf = Console.ReadLine();
int a = Convert.ToInt32(buf);
// Ввод вещественного числа
Console.WriteLine("Введите вещественное число");
buf = Console.ReadLine();
double b = Convert.ToDouble(buf);
// Ввод вещественного числа
Console.WriteLine("Введите вещественное число");
buf = Console.ReadLine();
float c = float.Parse(buf);
// Ввод целого числа
Console.WriteLine("Введите целое число");
buf = Console.ReadLine();
ulong d = ulong.Parse(buf);
}
}
}
В первых двух случаях используется класс Convert с соответствующими методами ToInt32()
и ToDouble(). Конечно это не все возможные преобразования, которые можно осуществить с
помощью данного класса. Этат класс поддерживает множество преобразований одних базовых
типов в другие. В остальных случаях использовался метод Parse() соответствующих числовых
классов (float и ulong).
Оба варианта ввода возможны для переменных всех рассмотренных ранее базовых числовых
типов данных (см. пункт «3.3.3.1. Типы значений в C#»).
Рассмотренный вариант ввода данных с использованием промежуточной переменной buf
вовсе не обязателен, вместо нее в соответствующий метод можно сразу подставить метод
Console.ReadLine():
int a = Convert.ToInt32(Console.ReadLine());
или
ulong d = ulong.Parse(Console.ReadLine());
То есть выполнение метода преобразования будет отложено до ввода пользователем
значения, над которым затем будет осуществлено преобразование.
4.1.2. Консольный вывод
В классе Console определены несколько методов записи в стандартный выходной поток:
System.Console.Write() – записывает текстовое представление своего аргумента в
стандартный поток вывода.
System.Console.WriteLine() – записывает текстовое представление своего аргумента, за
которым следует текущий признак конца строки, в стандартный выходной поток.
Иными словаыми, метод Write() курсор на новую строку не перводит, а метод WriteLine() –
переводит.
Форматный вывод
Методы с одинаковыми именами, но разными параметрами называются перегруженными.
Компилятор определяет, какой из методов вызван, по типу передаваемых в него величин. Методы
вывода в классе Console перегружены для всех встроенных типов данных, кроме того,
предусмотрены варианты форматного вывода. Иными словами, в качестве аргументов методы
вывода могут принимать величины разных типов, при этом синтаксис их вызова не меняется.
До сих пор при выводе с помощью метода WriteLine() данные отображались в формате,
используемом по умолчанию. Но в среде .NET Framework определен достаточно развитый
механизм форматирования, позволяющий во всех деталях управлять выводом данных.
Форматированный ввод-вывод подробнее рассматривается далее, а до тех пор полезно
ознакомиться с некоторыми возможностями форматирования. Они позволяют указать, в каком
именно виде следует выводить значения с помощью метода WriteLine(). Благодаря этому
выводимый результат выглядит более привлекательно. Следует, однако, иметь в виду, что
механизм форматирования поддерживает намного больше возможностей, а не только те, которые
рассматриваются здесь.
При выводе списков данных в предыдущих примерах программ каждый элемент списка
приходилось отделять знаком +, как в следующей строке.
Console.WriteLine("Вы заказали " + 2 +" предмета по цене $" + 3 + " каждый.");
При этом, происходит неявное преобразование чисел 2 и 3 в текстовый формат, и
конкатенация (объединение или селивание) 5-и строк (“Вы заказали ”, “2”, “ предмета по цене $”
“3” “ каждый”) в одну с последующим её выводом на экран. Для явного преобразования объектов
в текст существует метод ToString(), определенный по всех стандартных классах C#.
Расмотренный способ вывода числовой информации удобен, но он не позволяет управлять
внешним видом выводимой информации. Например, при выводе значения с плавающей точкой
нельзя определить количество отображаемых десятичных разрядов. Рассмотрим оператор
Console.WriteLine("Деление 10/3 дает: " + 10.0/3.0);
который выводит следующий результат:
Деление 10/3 дает: 3.33333333333333
В одних случаях такого вывода может оказаться достаточно, а в других – он просто
недопустим. Например, в финансовых расчетах после десятичной точки принято указывать лишь
два десятичных разряда.
Для управления форматированием числовых данных служит другая форма метода
WriteLine(), позволяющая встраивать информацию форматирования, как показано ниже.
WriteLine("форматирующая строка", arg0, argl, ... , argN);
В этой форме аргументы метода WriteLine() разделяются запятой, а не знаком +. А
форматирующая строка состоит из двух элементов: обычных печатаемых символов,
предназначенных для вывода в исходном виде, а также спецификаторов формата. Последние
указываются в следующей общей форме:
{argnum [,alignment] [:fmt]}
где argnum – номер выводимого аргумента, начиная с нуля; alignment – определяет выравнивание
и длину строки вывода; fmt – формат. Параметры alignment и fmt являются необязательными.
Если во время выполнения в форматирующей строке встречается спецификатор формата, то
вместо него подставляется и отображается соответствующий аргумент, обозначаемый параметром
argnum. Таким образом, местоположение спецификатора формата в форматирующей строке
определяет место отображения соответствующих данных. Параметры alignment и fmt указывать
необязательно. Это означает, что в своей простейшей форме спецификатор формата обозначает
конкретный отображаемый аргумент. Например, спецификатор {0} обозначает аргумент arg0,
спецификатор {1} – аргумент arg1 и т.д.
Начнем с самого простого примера. При выполнении оператора
Console.WriteLine("В феврале {0} или {1} дней.", 28, 29);
получается следующий результат.
В феврале 28 или 29 дней
Как видите, значение 28 подставляется вместо спецификатора {0}, а значение 29 – вместо
спецификатора {1}. Следовательно, спецификаторы формата обозначают место в строке, где
отображаются соответствующие аргументы (в данном случае – значения 28 и 29). Кроме того,
обратите внимание на то, что дополнительные значения разделяются запятой, а не знаком +.
Ниже приведен видоизмененный вариант предыдущего оператора, в котором указывается
ширина полей (то есть число символов, используемых для вывода аргумента).
Console.WriteLine("В феврале {0,10} или {1,5} дней.", 28, 29);
Выполнение этого оператора дает следующий результат.
В феврале
28 или
29 дней.
Как видите, неиспользуемые части полей заполнены пробелами. Напомним, что
минимальная ширина поля определяется параметром alignment. Если требуется, она может быть
превышена при выводе результата.
Разумеется, аргументы, связанные с командой форматирования, не обязательно должны быть
константами. Ниже приведен пример программы, которая выводит результат возведения числа в
квадрат и куб. В ней команды форматирования используются для вывода соответствующих
значений.
// Применить команды форматирования.
using System;
class DisplayOptions
{
static void Main()
{
int i=3;
Console .WriteLine ("Число\tКвадрат\tКуб");
Console.WriteLine("{0}\t{1}\t{2}", i, i*i, i*i*i);
}
}
Результат выполнения этой программы выглядит следующим образом.
Число Квадрат Куб
3
9
27
В приведенных выше примерах сами выводимые значения не форматировались. Но ведь
основное назначение спецификаторов формата – управлять внешним видом выводимых данных.
Чаще всего форматированию подлежат следующие типы данных: с плавающей точкой и
десятичный. Самый простой способ указать формат данных – описать шаблон, который будет
использоваться в методе WriteLine(). Для этого указывается образец требуемого формата с
помощью символов #, обозначающих разряды чисел. Кроме того, можно указать десятичную
точку и запятые, разделяющие цифры. Ниже приведен пример более подходящего вывода
результата деления 10 на 3.
Console.WriteLine("Деление 10/3 дает: {0:#.##}", 10.0/3.0);
Выполнение этого оператора приводит к следующему результату.
Деление 10/3 дает: 3.33
В данном примере шаблон #.## указывает методу WriteLine() отобразить два десятичных
разряда в дробной части числа. Следует, однако, иметь в виду, что метод WriteLine() может
отобразить столько цифр слева от десятичной точки, сколько потребуется для правильной
интерпретации выводимого значения.
Рассмотрим еще один пример. Оператор
Console.WriteLine("{0:###,###.##}", 123456.56);
дает следующий результат.
123,456.56
Аналогично, вместо # можно использовать 0. Разница в том, что если в шаблоне указано
большее число разрядов, чем нужно, то при использовании # будут выведены только значащие
разряды, а если использовать 0 – лишние разряды заполнятся 0. Пример:
Console.WriteLine("{0:#####.##}", 123.45656);
Console.WriteLine("{0:#####.##}", 123.45656);
Console.WriteLine("{0:0.##}", 123.45656);
Console.WriteLine("{0:0000.000}", 123.45656);
дают следующий результат:
123.46
123.46
123.46
0123.457
Обратите внимание, что при уменьшении числа разрядов, отводимых для вывода дробной
части, значение округляется по правилам математики. Кроме того, в шаблоне можно использовать
одновременно 0 и #.
4.1.3. Класс математических функций
Прежде чем перейти к рассмотрению примеров линейных программ, рассмотрим класс Math,
определенный в пространстве имен System. Он предоставляет константы и статические методы для
тригонометрических, логарифмических и иных общих математических функций. В таблице
показаны математическая запись функции, синтаксис вызова соответствующего метода, описание,
и типы данных, которые передаются этому методу:
Таблица 12. Методы и поля класса Math
Математическа
Синтаксис вызова в
Описание
я запись
программе на C#
Тригонометрические функции
arcsin(x)
System.Math.Asin(x)
Возвращает угол (в радианах), синус которого
равен x. Типы входной переменной x: duoble.
arccos(x)
System.Math.Acos(x)
Возвращает угол (в радианах), косинус которого
равен x. Типы входной переменной x: duoble.
arctan(x)
System.Math.Atan(x)
Возвращает угол (в радианах), тангенс которого
равен x. Типы входной переменной x: duoble.
System.Math.Atan2(y, x) Возвращает угол (в радианах), тангенс которого
равен отношению y / x. Типы входных переменных
y, x: duoble.
cos(x)
cosh(x)
sin(x)
sinh(x)
tan(x)
tanh(x)
x
ex
ln(x)
lg(x)
logy(x)
xy
x
π
e
Возвращает косинус x (x – угол в радианах). Типы
входной переменной x: duoble.
System.Math.Cosh(x)
Возвращает гиперболический косинус x (x – угол в
радианах). Типы входной переменной x: duoble.
System.Math.Sin(x)
Возвращает синус x (x – угол в радианах). Типы
входной переменной x: duoble.
System.Math.Sinh(x)
Возвращает гиперболический синус x (x – угол в
радианах). Типы входной переменной x: duoble.
System.Math.Tan(x)
Возвращает тангенс x (x – угол в радианах). Типы
входной переменной x: duoble.
System.Math.Tanh(x)
Возвращает гиперболический тангенс x (x – угол в
радианах). Типы входной переменной x: duoble.
Функции работы со знаком, округления
System.Math.Abs(x)
Возвращает абсолютное значение (модуль) числа x.
Типы входной переменной x: duoble, float, decimal,
sbyte, short, int, long.
System.Math.Sign(x)
Возвращает знак числа x. Типы входной
переменной x: duoble, float, decimal, sbyte, short, int,
long.
System.Math.Truncate(x) Вычисляет целую часть x. Типы входной
переменной x: duoble, decimal.
System.Math.Ceiling(x)
Возвращает наименьшее целое число, которое
больше или равно x. Типы входной переменной x:
duoble, decimal.
System.Math.Floor(x)
Возвращает наибольшее целое число, которое
меньше или равно x. Типы входной переменной x:
duoble, decimal.
System.Math.Round(x)
Округляет x до ближайшего целого. Типы входной
переменной x: duoble, decimal.
Степени и логарифмы
System.Math.Exp(x)
Возвращает e, возведенную в степень x. Типы
входной переменной x: duoble.
System.Math.Log(x)
Возвращает натуральный логарифм (по основанию
e) от x. Типы входной переменной x: duoble.
System.Math.Log10(x)
Возвращает логарифм по основанию 10 от x. Типы
входной переменной x: duoble.
System.Math.Log(x, y)
Возвращает логарифм по основанию y от x. Типы
входных переменных x, y: duoble.
System.Math.Pow(x, y)
Возвращает число x, возведенное в степень y. Типы
входных переменных x, y: duoble.
System.Math.Sqrt(x)
Возвращает корень квадратный из числа x. Типы
входной переменной x: duoble.
Константы
System.Math.PI
Представляет отношение длины окружности к ее
диаметру, определяемое константой π (π =3.14…).
System.Math.E
Представляет основание натурального логарифма,
определяемое константой e (e =2.718…).
System.Math.Cos(x)
4.1.4. Примеры линейных программ
Пример 1. Рассчитать площадь шара в кв. см. Радиус шара ввести с клавиатуры в
миллиметрах.
using System;
class Example1
{
static void Main()
{
double area; //площадь шара
int r; //радиус
Console.WriteLine("Введите радиус круга");
r = Convert.ToInt32(Console.ReadLine());
area = 4 * Math.PI * r * r / 100;
Console.WriteLine("Площадь шара = {0:0.###}",area);
Console.ReadLine();
}
}
В начале программы объявляем 2 переменных для хранения вычисляемой площади круга
(area) и его радиуса (r). Затем выводим строку – приглашение пользователю ввести радиус круга.
Затем считываем пользовательские данные и конвертируем их в число. Результат записываем в
переменную r. После этого вычисляем площадь круга и записываем в переменную area. Важное
замечание – математические выражения записываются по правилам математики, и
приоритеты арифметических операторов такие же. Кроме того, при вычислении значения
переменной area использовали константу PI класса Math. Поскольку в начале программы мы
используем пространство имен System (1 строка – using System;), то вводить полное имя нет
необходимости, достаточно Math.PI. После вычисления площади круга выводим ее значение в
формате 0.### – то есть для вывода целой части используется необходимое число символов, а для
вывода дробной – только три разряда. Последний оператор (Console.ReadLine();) ожидает нажатие
клавиши <Enter>. Он используется для того, чтобы приложение не закрывалось после выполнения
подсчетов и вывода результатов, и у пользователя была возможность увидеть результат, прежде
чем завершить выполнения приложения нажатием клавиши <Enter>.
Пример 2. Осуществить расчеты по формуле:
0.5 a 2  b 2  sin(    15 )  c 2  d 2  sin(    75 )
Y  arctg
a 2  b 2  cos(    15 )  c 2  d 2  cos(    75 ) ,
где φ=arctg(b/a), ψ=arctg(d/c), c=n*a, d=m*b.
Поскольку набор символов, используемых в идентификаторах переменных в программе
(латиница), не включает традиционные для тригонометрии символы греческого алфавита α, β, φ,
ψ, необходимо составить таблицу имен, которая установит соответствие между идентификаторами
переменных и этими символами. В таблице имен мы также зафиксируем промежуточные
(рабочие) переменные, упрощающие программирование исходной формулы:
Математическая величина, выражение
α
β
φ
ψ
α + φ + 15°
β + ψ + 75°
a 2  b2
c2  d 2
Идентификатор переменной в программе
alpha
beta
fi
psi
summAlphaFi
summBetaPsi
euclideanNormAB
euclideanNormCD
Программирование линейных вычислительных процессов очень похоже на вычисления по
формулам, которые математик осуществляет на бумаге. Алгоритм таких вычислений, как правило,
не составляется в виде блок-схем. Наиболее удобной формой представления такого алгоритма
является формульно-словесный способ, при котором действия пронумерованы пунктами 1, 2, 3 и
т.д. Каждое действие поясняется словами, формулами и расчетами.
Алгоритм решения этой задачи описан формульно-словесным способом:
1. Ввод с клавиатуры параметров a, b, m, n, alpha, beta.
2. Вычисление аргументов тригонометрических функций по формулам:
rad 

,
180 summAlphaFi      15  rad , summBetaPsi     75  rad .
где summAlphaFi и summBetaPsi промежуточные рабочие переменные, которые в исходной
формуле встречаются по два раза в числителе и знаменателе, следовательно, для сокращения
времени выполнения программы и сокращения вычислений одинаковые выражения вычисляются
и результат записывается в промежуточную переменную. Впоследствии, в программе просто
происходит вызов значения этой переменной, а не повторное вычисление выражения. Следует
отметить, что аргументы методов функций Sin() и Cos() должны задаваться в радианах. В
исходной формуле подразумевается, что углы α, β, φ, ψ измеряются в радианах. Поэтому углы 15°
и 75° градусов подлежат пересчету в радианы, что и сделано в приведенных выше формулах для
расчета summAlphaFi и summBetaPsi.
3. Последовательное вычисление величин с, d, fi, psi по формулам:
c = n*a, d = m*b, fi = arctg(b/a), psi = arctg(d/c).
4. Нахождение значений промежуточных переменных euclideanNormAB и euclideanNormCD
по формулам:
euclideanNormAB  a 2  b2 , euclideanNormCD  c2  d 2
5. Вычисление Y по упрощенной формуле за счет уже выполненных в предыдущих пунктах
алгоритма расчетов.
0.5* euclideanNormAB *sin( summAlphaFi)  EuclideanNormCD *sin( summBetaPsi)
Y  arctg
euclideanNormAB *cos( summAlphaFi)  EuclideanNormCD *cos( summBetaPsi)
6. Последним пунктом этого алгоритма является вывод найденного значения Y на экран
монитора.
using System;
class Example2
{
static void Main()
{
//объявляем переменные
double a, b, c, d, n, m, Y, alpha, beta, fi, psi, sqab, sqcd, af, bp;
//ввод переменных a, b, m, n
Console.WriteLine("Введите значения a, b, m, n");
a = Convert.ToDouble(Console.ReadLine());
b = Convert.ToDouble(Console.ReadLine());
m = Convert.ToDouble(Console.ReadLine());
n = Convert.ToDouble(Console.ReadLine());
//ввод переменных alpha и beta
Console.WriteLine("Введите значения alpha, beta");
alpha = Convert.ToDouble(Console.ReadLine());
beta = Convert.ToDouble(Console.ReadLine());
//производим последовательные вычисления
c = n * a;
d = m * b;
fi = Math.Atan2(b, a);
psi = Math.Atan2(d, c);
const double rad=Math.PI / 180;
summAlphaFi = alpha + fi + 15 * rad;
summBetaPsi = beta + psi + 75 * rad;
euclideanNormAB = Math.Sqrt(a * a + b * b);
euclideanNormCD = Math.Sqrt(c * c + d * d);
Y = Math.Atan2(
0.5*euclideanNormAB *Math.Sin(summAlphaFi)+euclideanNormCD*Math.Sin(summBetaPsi),
euclideanNormAB *Math.Cos(summAlphaFi)+ euclideanNormCD*Math.Cos(summBetaPsi));
Console.WriteLine("Y = {0:#.###}",Y);
Console.ReadLine();
}
}
Следует выделить следующие типичные действия программиста при разработке программ
такого класса (формализация линейного вычислительного процесса).
1. Формирование имен. На этом этапе подбираются латинские обозначения
(идентификаторы) для отображения в программе математических величин, используемых в
формулах. Для некоторых выражений, встречающихся в формулах два и более раза, нужно ввести
свои идентификаторы (временные переменные). Эти величины рассчитываются один раз перед
основной формулой (формулами), что упрощает исходные формулы и ускоряет расчеты.
2. Учитывая последовательный принцип выполнения операторов в программе – друг за
другом по мере их написания – необходимо установить порядок расчета формул. Основное
требование состоит в том, чтобы при расчете формулы все переменные и параметры были ранее
вычислены или введены с клавиатуры. Если формулы можно упростить путем алгебраических
преобразований, то это нужно сделать до начала программирования.
3. Все математические величины нужно разбить на две группы: константы и переменные.
Если есть возможность, лучше использовать константы (в примере кнстанта – rad), так как это
позволит ускорить вычисления.
4. Проанализировав возможные значения переменных и требуемую точность расчетов,
следует определить тип каждой переменной.
5. Требуется проанализировать все переменные и определить, какие из них вводятся с
клавиатуры, а какие вычисляются по ходу программы.
6. Если в тригонометрических функциях в качестве аргументов используются величины в
градусах, то необходимо в программе сделать преобразование этих величин в радианы.
7. При выводе результатов расчетов на экран нужно выбрать формат, способ представления
результатов (с плавающей или с фиксированной точкой) и задать точность (число значащих
чисел).
Пример 3. Не используя методы POW() и Log(double, double) класса Math пространства имен
System, осуществить расчеты по формуле:
Y  n X n1  Log n | X  1|
Для решения этой задачи следует использовать известные математические преобразования,
которые приведут исходную формулу к виду, удобному для программирования. Эти
преобразования описаны в следующей таблице:
Исходная формула
n
z , z>0
n+l
z , z>0
logn|x +1|
Формула для программирования
eln ( z )/ n
e( n1)*ln ( z )
ln(| x  1|)
ln(n)
using System;
class Example3
{
static void Main()
{
//объявляем переменные
double x, y;
int n;
Console.WriteLine("Введите значения x, n");
x = Convert.ToDouble(Console.ReadLine());
Текст программы
Math.Exp(Math.Log(z)/n)
Math.Exp((n+1)* Math.Log (z))
Math.Log(abs(x+1))/ Math.Log(n)
n = Convert.ToInt32(Console.ReadLine());
y = Math.Exp(Math.Log(Math.Abs(Math.Exp((n+1)*Math.Log(x))+
Math.Log(Math.Abs(x+1))/Math.Log(n)))/n);
Console.WriteLine("Y = {0:#.###}",y);
Console.ReadLine();
}
}
Обратите внимание на строки, в которых вычисляется зачение переменной y. Поскольку
строка оказалась слишком длинной, мы разбили ее на 2 строки. Хорошо, что C# не обращает
внимание на «лишние» пробелы и переходы на новую строку в коде программы.
Пример 5. Проверить, попадает ли число x в некоторый диапазон [a, b). То есть
.
Диапазон представляет собой 2 одновременно выполняющихся условия:
1) x меньше b
2) x больше или равно a
На языке C# логическое выражение, возвращающее истину, если x попадает в диапазон [a, b)
и ложь – в противном случае, имее вид:
(x >= a) && (x < b)
Пример 6. Проверить, попадает ли число x либо в диапазон [a, b), либо в (c, d). То есть
.
В данном случае x принадлежит одному из диапазонов [a, b) или (c, d).
На языке C# логическое выражение, возвращающее истину, если x попадает в один из
указанных диапазонов и ложь – в противном случае, имее вид:
((x >= a) && (x < b)) || ((x >= c) && (x < d))
Пример 7. Проверить, является ли целое число x – четным или нечетным.
Стандартный метод. Вычислить остаток от деления числа на 2, и если он равен 0, значит
число четое, если равен 1 – не четное.
(x % 2) == 0
(x % 2) == 1
(x % 2) != 0
// Истина, если число четное, Ложь в противном случае.
// Истина, если число не четное, Ложь в противном случае.
// Истина, если число не четное, Ложь в противном случае.
Как видите, можно проверять на равенство, или аборот на не равенство. Но последнее
выражение не стоит использовать, поскольку оно неверно с точки зрения понимания кода.
Более эффективный вариант. Использовать поразрядное И или ИЛИ. Особенность операции
И состоит в том, что ее результат истенен, только если оба операнда – истинны. С другой стороны,
у не четного числа послений разряд всегда равен 1, а у четного – нулю. Поэтому результат
поразрядной операции И числа и единицы равен 1 для не четного числа и 0 для четного.
(x & 1) == 1
(x & 1) == 0
// Истина, если число не четное, Ложь в противном случае.
// Истина, если число четное, Ложь в противном случае.
Рассмотрим пример порязрядного И между 1 и числами 70 и 43 в двоичном представлении:
4310 -> 1010112
110 -> 000001 2
& -> 0000012 -> 110
7010 -> 10001102
110 -> 00000012
& -> 00000002 -> 010
Пример 8. Выделить целую и дробную части вещественного числа x.
double frac;
int integer;
double x = Convert.ToDouble(Console.ReadLine());
integer = (int)x;
// целая часть
frac = x - integer; // дробная часть
Пример 9. Выделить n-й разряд целой части и m-й разряд дробной части числа. Нумерация
разрядов целой части начинается с младшего разряда, а дробной части – со старшего разряда.
using System;
class Program
{
static void Main(string[] args)
{
int n, m;
n = 3;
m = 2;
int fracM;
int integerN;
double x = Convert.ToDouble(Console.ReadLine());
fracM = (int)(x * Math.Pow(10, m)) % 10;
integerN = (int)(x / Math.Pow(10, n-1)) % 10;
Console.WriteLine("{0}-й разряд целой части введенного числа равен {1}", n, integerN);
Console.WriteLine("{0}-й разряд дробной части введенного числа равен {1}",m,fracM);
Console.ReadLine();
}
}
Пример 10. Определить, равен ли n-й (n < 16) разряд единице в двоичном представлении
целого числа x. Нумерация разрядов начинается с младшего, он имеет номер 0.
using System;
class Program
{
static void Main(string[] args)
{
int n;
n = 3;
int x = Convert.ToInt32(Console.ReadLine());
bool is2NinNumber;
int powNOfTwo = 1 << n;
is2NinNumber = (x & powNOfTwo) == powNOfTwo;
string str = is2NinNumber ? (n.ToString() + "-й разряд равен 1") :
(n.ToString() + "-й разряд равен 0");
Console.WriteLine(str);
Console.ReadLine();
}
}
Обратите внимание на строчку кода
n.ToString() + "-й разряд равен 1"
Обработку строк мы рассмотрим позднее, но здесь нужно сказать, что оператор + для
операндов – строк осуществляет их конкатенацию. То есть добавляет в конец строки, находящейся
слева от оператора строку, находящуюся справа от оператора.
Например, следующий фрагмент кода
string str = "Я, " + "снова Я, " + "опять Я";
Console.WriteLine(str);
выведет на экран строку:
Я, снова Я, опять Я
Кроме того, метод ToString(),вызываемый для переменной n:
n.ToString()
преобразует числовое значение, хранящееся в ней, в строку.
Таким образом, в выражении
n.ToString() + "-й разряд равен 1"
сначала производится преобразование числа, хранящегося в переменной n в строку, а затем
оператор + добавляет к ней строку «-й разряд равен 1», в итоге получаем: «3-й разряд равен 1».
1/--страниц
Пожаловаться на содержимое документа