Перейти к содержанию
СофтФорум - всё о компьютерах и не только

Вычисление арккосинуса в паскале


Рекомендуемые сообщения

Привет, народ. Вот в универе по 3-ей Лабе мне надо решить задачу:

Если три данных числа могут являться сторонами остроугольного треугольника, то найти его площадь и наименьший острый угол.

Само решение понятно, но есть один вопрос, да и хотелось бы, чтобы вы проверили мое решение и дали советы – может можно как нибудь лучше решить.

Сначала выясним, могут ли эти длины (а, b, c) являться сторонами треугольника. Для того, чтобы они являлись таковыми, необходимо, чтобы a+b>c and b+c>a and a+c>b.

Теперь найдем углы по теореме косинусов:

c*c=a*a+b*b-2*a*b*cos(c1), где с1 –угол против стороны с

Получим:

C1=arccos((a*a+b*b-c*c)/2*a*b)

Аналогично

A1=arccos((b*b+c*c-a*a)/2*b*c)

B1=arccos((a*a+c*c-b*b)/2*a*c)

Площадь треугольника будет равна:

S=sqrt(p(p-a)(p-b)(p-c)), где р – полупериметр

Ну угол наименьший я собираюсь найти сравнением С1 с А1, затем меньшее сравнить с В1.

Код напишу завтра. Ну как вам мое решение?

Единственный вопрос – как в паскале вычислять арксинус, арккосинус??????

Ссылка на комментарий
Поделиться на другие сайты

Бумер:

О вычислении в Паскале арксинуса и арккосинуса: эти функции не были введены Виртом, так как арксинус легко выражается через арктангенс, который в Паскале есть, а арккосинус - через арксинус. Конкретно, arcsin x = arctg x/(√(1-x²)), а arccos x = π/2 - arcsin x

Выведенные формулы у тебя записаны неточно. Наводящий вопрос: сколько будет 2/2*2 ?

Если правильно запишешь, все должно получиться :) .

Ссылка на комментарий
Поделиться на другие сайты

program lab_3;vara,b,c,a1,b1,c1,x1,x2,x3,s,min_ug,p: real;beginwrite ('wwedite a,b,c');read (a,b,c);if ((a+b)>c) and ((a+c)>b) and ((b+c)>a) then writeln ('eti chisla mogut bit storonami treugolnika')  else writeln ('eti chisla ne mogut bit storonami treugolnika');x1:=(a*a+b*b-c*c)/(2*a*b);c1:=(Pi/2)-arctan(x1/(sqrt(1-(x1*x1))));x2:=(b*b*+c*c-a*a)/(2*b*c);a1:=(Pi/2)-arctan(x2/(sqrt(1-(x2*x2))));x3:=(a*a+c*c-b*b)/(2*a*c);b1:=(Pi/2)-arctan(x3/(sqrt(1-(x3*x3))));min_ug:=0;if a1<b1 then min_ug:=a1 else min_ug:=b1;if min_ug>c1 then min_ug:=c1 else writeln ('minimalnii ugol w treugolnike rawen',min_ug,' radian');p:=(a+b+c)/2;s:=sqrt(p*(p-a)*(p-b)*(p-c));writeln ('ploschad S=',s);end.

Вот, написал код - Паскаль вроде не ругается.

Только еще есть вопросы:

1. Как перевести угол в градусы из радиан?

2. Что надо писать в коде, если требуется такое: Если (if) условие , то (then) какое нибудь действие пишем, иначе (else) а если это условие не выполняется, то надо продолжать выполнение программы не меняя значений переменных и не выводя ничего на экран, то как это записать. И как такое же записать, но если условие выполняется то надо ничего не делать (продолжить дальше выполнять программу), а если иначе (не выполняется условие), то какое-то действие. То как записывать это "ничего не делать" (имеется в виду продолжение выполнения программы)

Желательно с примерами. Заранее спасибо.

Кстати, на защите преподша у меня спросила: " К какому типу относится логический тип" Я ей и объяснил: К ЛОГИЧЕСКОМУ типу он и относится. ОНа сказала, что подготавливайся - на следующем занятии будешь еще пытаться защитить лабу номер два. В лекции я потом прочитал, что она диктовала "Логический тип (целый)" Так это ее выдумки или в реале так?

НИ в какой книжке подобного я не нашел...

Ссылка на комментарий
Поделиться на другие сайты

Бумер:

Пример у тебя написан почти правильно. То, что Паскаль не ругается, значит не очень много - только то, что нет синтаксических ошибок. А большинство ошибок обычно семантические, то есть ошибки в логике программы.

Высший судья, как всегда, тест на нескольких примерах, чтобы проверить разные разветвления в условных операторах, а при просмотре текста программы часто чего-то и не заметишь.

Во всяком случае, видно, что у тебя даже если в начале выполнения программы будет установлено, что треугольника не может существовать, все равно дальнейшие вычисления выполняются и липовые результаты (или ошибки) выдаются. Кроме того, оператор if min_ug>c1 then min_ug:=c1 else writeln ('minimalnii ugol w treugolnike rawen',min_ug,' radian'); выдаст сообщение только если c1 - не минимальный угол, а если он минимальный, то программа ничего не выдаст. Правильно было бы, например, так:

if min_ug>c1 then min_ug:=c1;

writeln ('minimalnii ugol w treugolnike rawen',min_ug,' radian');

А строка min_ug:=0; не нужна, какой-нибудь угол все равно будет минимальным.

Кое-какие скобки у тебя излишни, например, c1:=(Pi/2)-arctan(x1/(sqrt(1-(x1*x1)))); можно проще записать как c1:=Pi/2-arctan(x1/sqrt(1-x1*x1));

Кроме того, на будущее старайся вместо read использовать readln, избежишь возможных ошибок при нескольких операторах чтения.

По вопросам.

1:

GrToRad:=Pi/180;

Angle:=Angle*GrToRad;

Можно записать это и одним оператором, но часто переводной коэффициент бывает нужен в нескольких местах программы.

2:

if ... then ...;

........;

Если тут условие не выполняется, то оператор после then (у меня он обозначен как ... ) тоже выполняться не будет и программа просто пойдет дальше.

Для второго случая есть три варианта:

а)

........;

if ... then else ...;

........;

Тут, как говорят, после then стоит пустой оператор, то есть ничего. Синтаксис Паскаля, да и всех других языков, допускает пустые операторы.

б) красивее будет так:

........;

if NOT(...) then ...;

........;

в) еще красивее - просто переписать условие наоборот, например, вместо if NOT(a>b) then ... можно написать if a<=b then ...

Этот же пример в записи по варианту а выглядел бы как if a>b then else ...

Логический тип - НЕ целый, обозначается он BOOLEAN, но поскольку принимает лабы преподавательница у тебя, а не ты у нее, то тебе придется на время сдачи лаба с ней согласиться. Прочитай басню о волке и ягненке Крылова.

Возможно, преподавательница имела в виду, что в Паскале в машинном представлении обычно true представляется как 1, а false как 0, но это совершенно необязательно, а арифметические операции к логическому типу, в отличие от целого, неприменимы.

P.S. Да, пока отвечал, забыл твой вопрос - он был относительно перевода в градусы из радианов, а я ответил о переводе градусов в радианы. Впрочем, это делается почти так же:

GrToRad:=Pi/180;

Angle:=Angle/GrToRad;

Или можно так:

RadToGr:=180/Pi;

Angle:=Angle*RadToGr;

Изменено пользователем Тролль
Ссылка на комментарий
Поделиться на другие сайты

Во - первых, спасибо, что помогаешь мне!

Во вторых: Если я окомпилирую программу, то если числа не могут быть сторонами треугольника программа просто выводит, что числа не могут быть сторонами и завершает работу.

А как сделать по правильному. По-моему надо делать точки перехода или метки. Пожалуйста, дай ссылку на такую инфу или сам напиши.

Вот я переработал немного код:

program lab_3;vara,b,c,a1,b1,c1,x1,x2,x3,s,min_ug, min_ug_grad,p: real;beginwrite ('wwedite a,b,c');readln (a,b,c);if ((a+b)>c) and ((a+c)>b) and ((b+c)>a) then writeln ('Eti chisla mogut bit storonami treugolnika! Wichislit minimalnii ugol i ploschad etogo treugolnika?')  else writeln ('Eti chisla ne mogut bit storonami treugolnika');readln;x1:=(a*a+b*b-c*c)/(2*a*b);c1:=(Pi/2)-arctan(x1/(sqrt(1-(x1*x1))));x2:=(b*b*+c*c-a*a)/(2*b*c);a1:=(Pi/2)-arctan(x2/(sqrt(1-(x2*x2))));x3:=(a*a+c*c-b*b)/(2*a*c);b1:=(Pi/2)-arctan(x3/(sqrt(1-(x3*x3)))); if a1<b1 then min_ug:=a1 else min_ug:=b1;if min_ug>c1 then min_ug:=c1;min_ug_grad:=(180/Pi)*min_ug;writeln ('Minimalnii ugol w treugolnike rawen',min_ug,'radian ili',min_ug_grad,'gradusow');p:=(a+b+c)/2;s:=sqrt(p*(p-a)*(p-b)*(p-c));writeln ('ploschad S=',s);readln;end.
Ссылка на комментарий
Поделиться на другие сайты

Бумер:

Программа сейчас вообще не может посчитать что-нибудь правильно, поскольку в операторе x2:=(b*b*+c*c-a*a)/(2*b*c); семантическая ошибка, которую я сначала не заметил.

Например, введи стороны 3 4 5, и ты увидишь, что программа не выдает никаких результатов. То же будет, если треугольника не получается - программа все равно продолжает вычисления, корень получается из отрицательного числа, вычислить его программа не может и заканчивает выполнение, в отладочном режиме с сообщением об ошибке, а в скомпилированном варианте просто закончит работу. Естественно, это ненормальный выход из программы.

Ошибку в этом операторе ты легко найдешь сам.

Если подправить оператор, остается придумать, как нормально закончить работу программы, если треугольника не существует. Тут есть три варианта:

или перейти оператором goto на конец программы, но использование оператора goto в Паскале считается плохим стилем программирования,

или поставить всю оставшуюся часть программы внутрь условного оператора, используя begin ... end,

или - самый правильный способ - завершить выполнение программы вызовом специально предусмотренной для этого процедуры exit.

Кстати, в программе вопрос Eti chisla mogut bit storonami treugolnika! Wichislit minimalnii ugol i ploschad etogo treugolnika? чисто риторический, никаких вариантов ответа на него не предлагается. Его лучше вообще исключить, так в нем нет никакого смысла.

Тогда эта часть программы будет выглядеть так:

if ((a+b)>c) and ((a+c)>b) and ((b+c)>a)

then writeln ('Eti chisla mogut bit storonami treugolnika!')

else begin writeln ('Eti chisla ne mogut bit storonami treugolnika! Dlja vihoda nazhmite Enter'); readln; exit end;

Ну и кое-какие косметические улучшения:

вместо write ('wwedite a,b,c'); я бы написал writeln ('wwedite a,b,c, razdeljaja chisla probelami');

а вывод величин угла и площади оформил не в экспоненциальной форме записи, а в обычной, то есть как

writeln ('Minimalnii ugol w treugolnike rawen ',min_ug:4:2,' radian ili ',min_ug_grad:6:2,' gradusow');

и

writeln ('ploschad S=',s:10:2);

Ссылка на комментарий
Поделиться на другие сайты

вместо write ('wwedite a,b,c'); я бы написал writeln ('wwedite a,b,c, razdeljaja chisla probelami');

А может так:

writeln('Введите сторону а');

readln(a);

writeln('Введите сторону а');

readln(b);

writeln('Введите сторону а');

readln©;

Кстати, в Паскале язык переключается на русский:правый шифт+левый контрол, а на буржуйский левый шифт+правый контрол...

Изменено пользователем Feur_GOR
Ссылка на комментарий
Поделиться на другие сайты

Бумер:

Кстати, на защите преподша у меня спросила: " К какому типу относится логический тип" Я ей и объяснил: К ЛОГИЧЕСКОМУ типу он и относится. ОНа сказала, что подготавливайся - на следующем занятии будешь еще пытаться защитить лабу номер два. В лекции я потом прочитал, что она диктовала "Логический тип (целый)" Так это ее выдумки или в реале так?
Да, еще относительно логического типа: логический тип - НЕ целый, но к какому типу он относится, сказать можно. Логический тип является одним из встроенных порядковых простых типов. Целый тип, кстати, тоже относится к этому семейству. Иногда простые типы иначе называют скалярными, а встроенные - стандартными, но скорее всего, преподавательницу интересовало слово "порядковый".
Ссылка на комментарий
Поделиться на другие сайты

x2:=(b*b*+c*c-a*a)/(2*b*c);

По поему здесь семантич. ошибки нет. какая здесь может быть ошибка?

А вот в c1:=(Pi/2)-arctan(x1/(sqrt(1-(x1*x1)))); Корень можно извлекать только из неотрицат. числа. А как это записать (что должна прога выводить, если подкоренное выражение меньше нуля?)

Ссылка на комментарий
Поделиться на другие сайты

Бумер:

По поему здесь семантич. ошибки нет. какая здесь может быть ошибка?
Сравни выражения для вычисления x1, x2, x3. Они должны быть однотипными, а у тебя выражение для x2 отличается от двух других.

x2:=(b*b*+c*c-a*a)/(2*b*c);

Красным выделен лишний знак умножения. Так, как у тебя было записано, выражение в скобках эквивалентно (b*b*c*c-a*a), а не (b*b+c*c-a*a), как следовало написать (и было написано в других случаях). Кстати, вопрос на засыпку :bye1: , почему эквивалентно. Сразу подсказка: посмотри описание операции "унарный плюс".

Я уже когда-то писал: компьютер никаких ошибок программирования не прощает, наоборот, работает по принципу "не было гвоздя - подкова пропала, подкова пропала - лошадь захромала, лошадь захромала - командир убит, конница разбита, армия бежит..." (из старого английского стишка).

что должна прога выводить, если подкоренное выражение меньше нуля?
Ну, хорошая прога в таком случае должна вывести нечто вроде "Извините, ошибка программиста. Пожалуйста, сообщите, при каких входных данных произошла эта ошибка. Это поможет нам улучшить программу. Спасибо!". На самом деле это та самая захромавшая лошадь из-за лишнего знака умножения. Подкоренное выражение на этом этапе выполнения программы не может быть отрицательным. Оно будет таким только для несуществующих треугольников, а эта возможность на данном этапе выполнения программы уже отсечена.

А вопрос об углах и площадях несуществующих треугольников хотя и интересен с математической точки зрения (и его разбор дал бы способ построить программу экономнее: может ли существовать треугольник с заданными сторонами, можно было узнать без всяких сравнений сторон, просто по ходу вычисления площади), но не будем уходить далеко от тех баранов, какие у нас есть.

Изменено пользователем Тролль
Ссылка на комментарий
Поделиться на другие сайты

Защитил вторую лабу, можете поздравить!

Третью решил полностью пределатЬ, т.к. в ней много глюков и не учтено ОДЗ, которое от нас очень сильно требуют.

вот код

program lab_3;vara,b,c,a1,b1,c1,x1,x2,x3,s,min_ug, min_ug_grad,p: real;beginwrite ('wwedite a,b,c');readln (a,b,c);if ((a+b)>c) and ((a+c)>b) and ((b+c)>a) then  beginwriteln ('Eti chisla mogut bit storonami treugolnika!');x1:=(a*a+b*b-c*c)/(2*a*b);c1:=(Pi/2)-arctan(x1/(sqrt(1-(x1*x1))));x2:=(b*b*+c*c-a*a)/(2*b*c);a1:=(Pi/2)-arctan(x2/(sqrt(1-(x2*x2))));x3:=(a*a+c*c-b*b)/(2*a*c);b1:=(Pi/2)-arctan(x3/(sqrt(1-(x3*x3)))); if a1<b1 then min_ug:=a1  else min_ug:=b1; if min_ug>c1 then min_ug:=c1;min_ug_grad:=(180/Pi)*min_ug;writeln ('Minimalnii ugol w treugolnike rawen ',min_ug:3:2,' radian ili ',min_ug_grad:3:2,' gradusow');p:=(a+b+c)/2;s:=sqrt(p*(p-a)*(p-b)*(p-c));writeln ('ploschad S=',s:3:2);readln;  end else  beginwriteln ('Eti chisla ne mogut bit storonami treugolnika');readln;  endend. 

Прошу посмотреть эту прогу на налчие багов и проверить, соответствет ли она прикрепленному ниже алгоритму и если нет то что лучше подправить алгоритм или прогу и как?.

Алгоритм_лаб_3__ТП_.JPG

post-34963-1160216861_thumb.jpg

Ссылка на комментарий
Поделиться на другие сайты

Бумер:

а) убери лишний знак умножения! Сколько об этом пишу, специально красным цветом его выделял, а воз и ныне там!

б) ОДЗ у тебя проверяется сравнением сторон. Проверку, что введенные длины сторон положительны, легко добавить к сравнению сторон. Хотя, возможно, это и излишне, хуже от этого не будет. Тогда вместо

if ((a+b)>c) and ((a+c)>b) and ((b+c)>a)

пишем

if (a+b>c) and (a+c>b) and (b+c>a) and (a>0) and (b>0) and (c>0)

А проверять иксы, как это у тебя нарисовано на блок-схеме, ни к чему. Если треугольник существует, а это у тебя проверяется вначале, они всегда будут меньше 1. Поскольку уже установлено, что треугольник существует, у него обязаны иметься три угла, это незачем проверять отдельно.

Изменено пользователем Тролль
Ссылка на комментарий
Поделиться на другие сайты

А код-то соответствует алгоритму?

ЗЫ: лишний знак умнож. убрал!

А лишнюю проверку ОДЗ от нас требуют!

Ссылка на комментарий
Поделиться на другие сайты

Вот последний, отлаженный вариант с моей точки зрения:

program lab_3;vara,b,c,p,s,x1,x2,x3,min_ug,min_ug_grad,a1,b1,c1,max,max_grad: real;beginwriteln ('wwedite a='); readln(a);writeln ('wwedite b='); readln(b);writeln ('wwedite c='); readln ©;if (a+b>c) and (a+c>b) and (b+c>a) thenbegin if (a>0) and (b>0) and (c>0) then  begin  x1:=(b*b+c*c-a*a)/(2*b*c);  x2:=(a*a+c*c-b*b)/(2*a*c);  x3:=(a*a+b*b-c*c)/(2*a*b);  if (x1<1) and (x2<1) and (x3<1) thenbegin a1:=Pi/2-arctan(x1/(sqrt(1-x1*x1))); b1:=Pi/2-arctan(x2/(sqrt(1-x2*x2))); c1:=Pi/2-arctan(x3/(sqrt(1-x3*x3)));  min_ug:=a1;  if min_ug>b1 then min_ug:=b1;  if min_ug>c1 then min_ug:=c1;  max:=a1;  if max<b1 then max:=b1;  if max<c1 then max:=c1;  max_grad:=(180/Pi)*max;  p:=(a+b+c)/2;  s:=sqrt(p*(p-a)*(p-b)*(p-c));  min_ug_grad:=(180/Pi)*min_ug;  if max_grad<90 thenbegin writeln('Ploshad S=',s:10:2); writeln ('Minimalnii ugol v treugolnike min_ug=',min_ug:10:2,'radian'); writeln( ' Ili', min_ug_grad:10:2,'gradusow'); endelse writeln ('treugolnik ne ostrougolnii');end  end else writeln ('naruscheno ODZ');endelse writeln ('Eti chisla ne mogut bit storonami treugolnika');readln;end.

Алгоритм тот же. ТАк соответствует ли этот код нарисованному алгоритму?

Ссылка на комментарий
Поделиться на другие сайты

Для публикации сообщений создайте учётную запись или авторизуйтесь

Вы должны быть пользователем, чтобы оставить комментарий

Создать учетную запись

Зарегистрируйте новую учётную запись в нашем сообществе. Это очень просто!

Регистрация нового пользователя

Войти

Уже есть аккаунт? Войти в систему.

Войти
  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...