Продолжаем
заниматься алгоритмизацией и программированием математических задач, уважаемые
подписчики! Все создаваемые нами
подпрограммы мы будем помещать на хранение в модуль Problem.
Поклянёмся
с вами в том, что никогда не забудем о важности математических знаний для
выработки умений и навыков профессионального программирования! Не так давно мне
поведали, что особей, способных только лишь программировать составленные кем-то
алгоритмы, в среде профессионалов нежно называют “быдлокодерами”.
РЕШЕНИЕ НЕРАВЕНСТВ И СИСТЕМ
1. Решение задачи “Неравенство”.
Задача V.2.8. “Неравенство”. Заданы
коэффициенты неравенства a * x > b. Построить подпрограмму
решения неравенства.
Математические
предпосылки решения неравенства таковы:
-если коэффициент
a > 0, то решением
неравенства будет выражение x > b / a;
например, неравенство 2 * x > 3 имеет решение x > 1.5;
-если коэффициент
a < 0, то решением
неравенства будет выражение x < b / a;
например, неравенство –2 * x > 3 имеет решение x < –1.5;
-если коэффициент
a = 0, а коэффициент b < 0, то решением
неравенства может быть любое значение x;
например, неравенство 0 * x > –5 справедливо при
произвольном x;
-если коэффициент
a = 0, а коэффициент b >= 0, то неравенство не
имеет решений; например, неравенство 0 x > 5
не может быть справедливым ни при каком x.
Таким образом,
подпрограмма решения неравенства должна иметь два результата. Основной
результат – граничное значение для x,
которое может быть вычислено не при любых значениях коэффициентов неравенства. Дополнительный
результат – флажок z, который для
всех случаев должен идентифицировать характер результата решения. Это
достигается присвоением ему значений соответствующих кодов, в том числе:
-код z = 1; решение следует
записать в виде x > c,
где с = b / a – граничное
значение;
-код z = 2; решение следует
записать в виде x < c,
где с = b / a – граничное
значение;
-код z = 3; следует сообщить, что
решением может быть произвольное значение x;
-код z = 4; следует сообщить, что
решения отсутствуют.
Оптимальный порядок
следования ветвей оператора ветвления совпадает со схемой математического
решения.
Procedure Inequality ( a,b: Real; Var c:
Real; Var z: Byte); Begin If a>0
Then Begin c:=b/a; z:=1 End Else If a<0
Then Begin c:=b/a; z:=2 End Else If
b<0 Then z:=3 Else z:=4 End;
Соответствующаяпрограммаимеетвид:
{$B+,D+,E+,I+,L+,N+,Q+,R+,X-}
Program V_02_08; Uses Problem; Var a,b,c: Real; z: Byte;
Begin Write('Введитекоэффициентынеравенстваa,b: '); ReadLn(a,b); Inequality(a,b,c,z); Case z Of 1: WriteLn('Решение: x > ',c:0:4); 2: WriteLn('Решение: x < ',c:0:4); 3: WriteLn('Решениепроизвольно'); 4: WriteLn('Решениеотсутствует'); End
End.
2. Решение задачи “Система”.
Задача V.2.7. “Система”. Заданы
коэффициенты и свободные члены системы двух линейных уравнений с двумя
неизвестными
Известно, что не
все коэффициенты системы a1, b1, a2, b2 равны нулю одновременно.
Построить подпрограмму решения системы.
Решение системы
двух линейных уравнений с двумя неизвестными можно реализовать по формулам
Крамера: – определители второго
порядка. Эти формулы образуются с помощью простого правила. Каждое из
неизвестных равно дроби, знаменатель которой есть определитель, составленный из
коэффициентов при неизвестных, а числитель получается из этого определителя
заменой коэффициентов при соответствующем неизвестном свободными членами.
Вычислить
определитель второго порядка очень легко. Для этого нужно найти разность
произведений его диагональных элементов. Например, значение определителя Δ можно вычислить
по формуле Δ = a1*b2 – a2*b1.
Исследования
этих формул показывают, что при решении системы могут представиться три
существенно различных случая.
-Определитель в
знаменателе отличен от нуля. Тогда система уравнений имеет единственное
решение, определяемое по формулам Крамера.
-Определитель в
знаменателе равен нулю. Оба определителя в числителях также равны нулю. Система
уравнений имеет бесчисленное множество решений.
-Определитель в
знаменателе равен нулю. Хотя бы один из определителей в числителе отличен от
нуля. Система уравнений не имеет решений.
Эти выводы справедливы
при условии, что не все коэффициенты системы a1, b1, a2, b2 равны нулю одновременно.
Это ограничение значений исходных данных указано непосредственно в условии
задачи.
Таким образом, подпрограмма
решения системы двух линейных уравнений с двумя неизвестными имеет три
результата. Основные результаты – значения неизвестных x и y, которые могут
быть вычислены не при любых значениях коэффициентов и свободных членов системы.
Дополнительный результат – флажок z,
который во всех случаях должен идентифицировать характер результата решения.
Это достигается присвоением ему значений соответствующих кодов (1 – единственное решение, 2 – множество решений, 3 – отсутствие решений).
Наиболее
целесообразно порядок следования ветвей оператора ветвления выбрать таким:
-проверка условия
V <> 0, где V – значение определителя в
знаменателе; в случае его истинности может быть получено единственное решение
системы; в дальнейшем условие V = 0
можно не проверять;
-проверка на
равенство нулю определителей в обоих числителях; в случае положительного ответа
имеем бесчисленное множество решений;
-во всех
остальных случаях система решений не имеет, что соответствует альтернативной
ветви оператора ветвления.
После вычисления
каждого из определителей в процедуре присутствуют операторы вида x := Int ( x * 1E10 ) / 1E10.
Они используются для уборки “мусора”. В данном случае это необходимо, чтобы
правильно вычислять определители тогда, когда они должны иметь нулевые значения.
В необходимости
этого убеждает пример системы уравнений . Эта система имеет бесчисленное множество решений, поскольку
все её определители равны нулю, в чём несложно убедиться вручную. А теперь проконтролируем
значения выражений a1*b2–a2*b1,
c1*b2–c2*b1
и a1*c2–a2*c1,
составив для этого простенькую программку. При этом получаем результаты 3.637978807110–12, 1.818989403510–12 и –7.275957614210–12
соответственно.
Отличия определителей
от нуля, возникшие по причине приближённого характера машинных вычислений, весьма
незначительны. Но даже столь небольшие отличия приводят к неправильному
определению характера результата решения и к получению несуществующих решений
системы уравнений. Благодаря же применению операторов вида x := Int ( x * 1E10 ) / 1E10
определители получают правильные нулевые значения.
ProcedureSystem_Equation(a1,b1,c1,a2,b2,c2:Real; Varx,y:Real; Varz:Byte); VarV,Vx,Vy: Real; Begin V := a1*b2-a2*b1; V := Int ( V*1E10 ) / 1E10; Vx := c1*b2-c2*b1; Vx := Int ( Vx*1E10 ) / 1E10; Vy := a1*c2-a2*c1; Vy := Int ( Vy*1E10 ) / 1E10; IfV<>0 ThenBeginx := Vx/V; y := Vy/V; z := 1 End ElseIf (Vx=0) And (Vy=0) Thenz:=2 Elsez:=3 End;
Уважаемые подписчики! Вы уже, наверное, обратили внимание на то, что теперь
мы значительно меньше уделяем внимания алгоритмическому языку, нежели ранее? Прислушайтесь
к себе и вы поймёте, что, как средство алгоритмизации ветвлений, АЯ вам уже не
нужен. Некоторые даже могут сказать, что он им был не нужен изначально. Это
нормально, поскольку человек, не являющийся педагогом-профессионалом, чаще
всего не отдаёт себе отчёт в том, откуда, каким путём и благодаря чему у него
появились те или иные знания.
Уважаемые подписчики!При
необходимости задать вопрос, проконсультироваться, уточнить или обсудить
что-либо обращайтесь через Гостевую
книгу моего персонального сайта http://a-morgun.narod.ru. При
этом настоятельно
рекомендую пользоваться браузером Internet
Explorer.