Поиск:

Ответ в темуСоздание новой темы Создание опроса
> [General] cуществует ли треугольник? 
:(
    Опции темы
TepH
Дата 24.10.2010, 18:27 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 24.10.2010

Репутация: нет
Всего: нет



Помогите пожалуйста. Нужно написать программу, по которой можно узнать по введённым длинам сторон, существует такой треугольник или нет, а если существует, то какой он: равносторонний, равнобедренный, прямо-,остро-, тупоугольный.
Так вот, я написал, но при вводе длин 0,3; 0,4; 0,5 программа выдаёт, что треугольник остроугольный, хотя должен выдавать, что прямоугольный. Судя по всему, это происходит из-за погрешности преобразований чисел в двоичный код и обратно. Если посмотреть просто на умножение этих чисел, представляя числа, как double precision, получается, что, как я полагаю при возведении в квадрат числа, квадрат которого равен меньше 0,1 , он выдаёт такую бяку. В итоге для квадрата числа 0,3 получается что-то вроде 0,090000642. Из-за этого и происходит ошибка. Подскажите пожалуйста, как избавиться от этого?

Вот текст мой программы:
Код

       program TRI
       real  a, b, c
       print*, 'Введите три стороны'
       read*,a,b,c
       s=a
       d=b
       do 10 i=1, 2
        if(s .lt. d) s=d
        d=c
 10    continue
       print*,'Наибольшая сторона:',s
       if(s .eq. a)then
          if(s .lt. b+c) then
           if(b**2+c**2 .gt. a**2) print*, 'Остроугольный'
           if(b**2+c**2 .lt. a**2) print*, 'Тупоугольный'
           if(b**2+c**2 .eq. a**2) print*, 'Прямоугольный'
            goto 20
           endif
 
       elseif(s .eq. b) then
          if(s .lt. a+c) then
           if(a**2+c**2 .gt. b**2) print*, 'Остроугольный'
           if(a**2+c**2 .lt. b**2) print*, 'Тупоугольный'
           if(a**2+c**2 .eq. b**2) print*, 'Прямоугольный'
            goto 20
           endif
 
       elseif(s .eq. c) then
          if(s .lt. a+b) then
           if(a**2+b**2 .gt. c**2) print*, 'Остроугольный'
           if(a**2+b**2 .lt. c**2) print*, 'Тупоугольный'
           if(a**2+b**2 .eq. c**2) print*, 'Прямоугольный'
            goto 20
           endif
       endif
         goto 40
 
 20    if(a .eq. b .and. a .eq. c) then
         print*, 'Равносторонний'
         goto 30
       endif
 
       if(a .eq. b .and. a .ne. c .or. a .eq. c .and. a .ne. b) goto 25
       if(b .eq. c .and. b .ne. a) then
        goto 25
        else
         goto 30
       endif
 
 25   print*, 'Равнобедренный'
 
 30    print*, 'Треугольник существует'
        goto 100
 40    print*, 'Треугольник не существует'
        goto 100
 
 
 100    end
 

PM MAIL   Вверх
FCM
Дата 24.10.2010, 19:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 461
Регистрация: 30.3.2009

Репутация: 8
Всего: 9



Сравнивать вещественные числа  не есть хорошо в любом языке программирования (в некоторых C++ компиляторах даже предусмотрены предупреждения на сей счет).
Можно попробовать задать некий малый порог  и сравнивать с ним модуль разности вещественных чисел.

Кроме того, real лучше заменить на real(8).

(И что за компилятор используется?
В современных (в т.ч. бесплатных) компиляторах 
- максимум двух и более чисел можно найти с помощью функции max(a,b,c, ...). 
- операторы сравнения  можно писать в естественной форме ==, >, < и т.п.
- циклы лучше писать в так называемой блочной форме do...enddo. )



Это сообщение отредактировал(а) FCM - 24.10.2010, 19:23
PM MAIL   Вверх
TepH
Дата 24.10.2010, 22:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 24.10.2010

Репутация: нет
Всего: нет



Компиллятор... Даже и не знаю. Мы делаем через программу Putty. Через неё заходим на Unix-сервер и там делаем.

"Можно попробовать задать некий малый порог  и сравнивать с ним модуль разности вещественных чисел."
Знать бы как... Я ж сам не программист, а тут начали проходить Фортран лабораторными работами, а по обучалке читаем теорию. Но там нет такого(там много чего нету). Преподы говорят, что надо бы, чтобы мы сами додумались...
PM MAIL   Вверх
Фантом
Дата 24.10.2010, 23:26 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вы это прекратите!
***


Профиль
Группа: Участник Клуба
Сообщений: 1516
Регистрация: 23.3.2008

Репутация: 5
Всего: 49



Цитата(TepH @  24.10.2010,  22:30 Найти цитируемый пост)
"Можно попробовать задать некий малый порог  и сравнивать с ним модуль разности вещественных чисел."
Знать бы как... 

Например, так:
Код

if(abs(a**2+c**2-b**2)<1E-6) print *, 'Прямоугольный'


PM   Вверх
FCM
Дата 25.10.2010, 08:28 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 461
Регистрация: 30.3.2009

Репутация: 8
Всего: 9



Цитата(Фантом @  24.10.2010,  23:26 Найти цитируемый пост)
Например, так:

if(abs(a**2+c**2-b**2)<1E-6) print *, 'Прямоугольный'



Поскольку там несколько подобных сравнений, лучше ввести отдельную переменную или константу 
и сравнивать с ней.
PM MAIL   Вверх
Фантом
Дата 25.10.2010, 09:56 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Вы это прекратите!
***


Профиль
Группа: Участник Клуба
Сообщений: 1516
Регистрация: 23.3.2008

Репутация: 5
Всего: 49



Цитата(FCM @  25.10.2010,  08:28 Найти цитируемый пост)
Поскольку там несколько подобных сравнений, лучше ввести отдельную переменную или константу 
и сравнивать с ней. 

Да, конечно.
PM   Вверх
FCM
Дата 25.10.2010, 13:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 461
Регистрация: 30.3.2009

Репутация: 8
Всего: 9



Программу можно построить по другому - введя подпрограмму сортировку (например так, чтобы a<=b<=c) чтобы не воодить s и не плодить if-ы




Это сообщение отредактировал(а) FCM - 25.10.2010, 14:02
PM MAIL   Вверх
TepH
Дата 25.10.2010, 13:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 24.10.2010

Репутация: нет
Всего: нет



Цитата(Фантом @  24.10.2010,  23:26 Найти цитируемый пост)
if(abs(a**2+c**2-b**2)<1E-6) print *, 'Прямоугольный'


Спасибо. С этим работает. Я, правда, не совсем понимаю, что это значит...
Странно, при вводе 3; 4; 5, он пишет просто прямоугольный, а при вводе 0,3; 0,4; 0,5 что и прямоугольный и остроугольный...

PM MAIL   Вверх
FCM
Дата 25.10.2010, 13:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 461
Регистрация: 30.3.2009

Репутация: 8
Всего: 9



Цитата(TepH @  25.10.2010,  13:36 Найти цитируемый пост)
Цитата(Фантом @  24.10.2010,  23:26 Найти цитируемый пост)
if(abs(a**2+c**2-b**2)<1E-6) print *, 'Прямоугольный'

Спасибо. С этим работает. Я, правда, не совсем понимаю, что это значит...
Странно, при вводе 3; 4; 5, он пишет просто прямоугольный, а при вводе 0,3; 0,4; 0,5 что и прямоугольный и остроугольный...


Потому что при введении eps надо согласовать все условия.

Программу можно построить по другому - введя подпрограмму сортировки , чтобы не воодить s и не плодить if-ы

Код

program TRI
       real(8) a, b, c, eps
       eps = 1.d-8
       print*, 'Enter 3 sides'
       read*, a,b,c
       call sort3(a,b,c) ! Сортируем так. чтобы a<=b<=c
       print*, a,b,c
       if( c<eps .or. b<eps .or. a<eps .or. (c - a - b)>eps  ) stop 'Treugolnik does not exist!'
       if( abs(a-b)<eps .and. abs(b-c)<eps )  then
          print*, 'Ravnostoronnii'
       else
           if( abs(a-b)<eps  .or. abs(c-b)<eps  .or. abs(a-c)<eps  ) print*,  'Ravnobedrennyi'
           if( (a*a + b*b - c*c) > eps )  then
              print*, 'Ostrougolnyi'
           else if( (a*a + b*b - c*c) < -eps ) then
              print*, 'Tupougolnyi'
           else
              print*, 'Pryamougolnyi'
           endif
       endif
end

subroutine sort3(a,b,c)
    real(8) a,b,c
    call sort2(a,b)  ! переставляем значения так , что a<=b
    call sort2(b,c)  ! переставляем значения так , что b<=c
    call sort2(a,b)  ! переставляем значения так , что a<=b
end

subroutine sort2(x,y)
    real(8) x, y, t
    if(x>y) then
       t = y
       y = x
       x = t
    endif
end


Выше 
- если используется f77,  оператор > надо заменить на .gt.  , а оператор < на .lt.
- еще неидеально относительно выбора eps - возможно его лучше выбирать исходя из величины наиболее длинной стороны или т.п.
- ну и надо проверить правильно ли работает сортировка 



Это сообщение отредактировал(а) FCM - 28.10.2010, 09:53
PM MAIL   Вверх
TepH
Дата 25.10.2010, 13:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 24.10.2010

Репутация: нет
Всего: нет



Что-то на вашу большую программу шибко ругается. 


Код

tri2.for:24.7:

       end
      1
Error: END IF statement expected at (1)
tri2.for:26.6:

      subroutine sort3(a,b,c)
     1
Error: Unclassifiable statement at (1)
tri2.for:27.16:

       real(8) a, b, c
               1
Error: Symbol 'a' at (1) already has basic type of REAL
tri2.for:30.6:

      end
     1
Error: END IF statement expected at (1)
tri2.for:32.6:

      subroutine sort2(x,y)
     1
Error: Unclassifiable statement at (1)
tri2.for:33.72:

       real(8) x, y, t
                                                                       1
Error: Unexpected data declaration statement at (1)
tri2.for:39.6:

      end
     1
Error: END IF statement expected at (1)
Error: Unexpected end of file in 'tri2.for'

PM MAIL   Вверх
FCM
Дата 25.10.2010, 14:05 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 461
Регистрация: 30.3.2009

Репутация: 8
Всего: 9



Попробй еще раз (ранее была неточность в sort3):
В gfortran работает.
Код

       program TRI
           real(8) a, b, c, eps
           eps = 1.d-8
           print*, 'Enter 3 sides'
           read*, a,b,c
           call sort3(a,b,c) ! Сортируем значения так, чтобы a<=b<=c
           print*, a,b,c
           if( c<eps .or. b<eps .or. a<eps .or. (a + b - c) < eps  ) stop 'Treugolnik does not exist!'
           if( abs(a-b)<eps .and. abs(b-c)<eps )  then
               print*, 'Ravnostoronnii'
           else
               if( abs(a-b)<eps  .or. abs(c-b)<eps  .or. abs(a-c)<eps  ) print*,  'Ravnobedrennyi'
               if( (a*a + b*b - c*c) > eps )  then
                   print*, 'Ostrougolnyi'
               else if( (a*a + b*b - c*c) < -eps ) then
                   print*, 'Tupougolnyi'
               else
                   print*, 'Pryamougolnyi'
               endif
            endif
       end

       subroutine sort3(a,b,c)
            real(8) a,b,c
            call sort2(a,b)  ! переставляем значения так , что a<=b
            call sort2(b,c)  ! переставляем значения так , что b<=c
            call sort2(a,b)  ! переставляем значения так , что a<=b
       end

       subroutine sort2(x,y)
           real(8) x, y, t
           if(x>y) then
               t = y
               y = x
               x = t
           endif
       end



А если продолжает ругаться выложи весь код, на который ругается - может при копировании и вставке ошибки?

Это сообщение отредактировал(а) FCM - 25.10.2010, 15:47
PM MAIL   Вверх
TepH
Дата 25.10.2010, 14:41 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 24.10.2010

Репутация: нет
Всего: нет



А теперь работает... Только тут такое дело, уж простите за то, что так гружу Вас, но если ввести, 1, 2, 3 то он пишет, что треугольник тупоугольный, а его, по-идее, не должно существовать (0н будет, так называемый, развёрнутый, т.е. прямая линия)... А в этой программе я даже не знаю, куда сунуться, чтобы это подправить. Что-то потыкался, а это вообще ничего не даёт.


А gfortran  - это название компиллятора чтоли?
PM MAIL   Вверх
FCM
Дата 25.10.2010, 15:35 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 461
Регистрация: 30.3.2009

Репутация: 8
Всего: 9



Вместо строки
Код

if( c<eps .or. b<eps .or. a<eps .or. (c - a - b)> eps ) stop 'Treugolnik does not exist!'

лучше так (в предыдущем своем посте тоже поправил)
Код

if( c<eps .or. b<eps .or. a<eps .or. (a + b - c)<eps ) stop 'Treugolnik does not exist!'


Цитата(TepH @  25.10.2010,  14:41 Найти цитируемый пост)
А gfortran  - это название компиллятора чтоли? 

gfortran - фортран-компилятор из GCC-коллекции (может использоваться как в Linux, так и в Windows). Текщая версия GCC 4.5.x.


Это сообщение отредактировал(а) FCM - 25.10.2010, 15:49
PM MAIL   Вверх
FCM
Дата 25.10.2010, 16:15 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 461
Регистрация: 30.3.2009

Репутация: 8
Всего: 9



Возможно, для упрощения, в данном примере, для вводимых чисел можно снять сравнение с использованием порога eps , и оставить eps-проверку только в критических местах. 
Будет примерно так:
 
Код

        program TRI
           real(8) a, b, c, eps
           eps = 1.d-8
           print*, 'Enter 3 sides'
           read*, a,b,c
           call sort3(a,b,c) ! Сортируем так. чтобы a<=b<=c
           print*, a,b,c
           if( c <= 0.d0 .or. b <= 0.d0 .or. a <= 0.d0 .or. (a + b - c) <= 0.d0 ) stop 'Treugolnik does not exist!'
           if( a == b .and. b == c )  then
               print*, 'Ravnostoronnii'
           else
               if( a == b  .or. c == b  .or. a == c  ) print*,  'Ravnobedrennyi'
               if( (a*a + b*b - c*c) > eps )  then
                   print*, 'Ostrougolnyi'
               else if( (a*a + b*b - c*c) < -eps ) then
                   print*, 'Tupougolnyi'
               else
                   print*, 'Pryamougolnyi'
               endif
           endif
       end

       subroutine sort3(a,b,c)
           real(8) a,b,c
           call sort2(a,b)  ! переставляем значения так , что a<=b
           call sort2(b,c)  ! переставляем значения так , что b<=c
           call sort2(a,b)  ! переставляем значения так , что a<=b
       end
      subroutine sort2(x,y)
           real(8) x, y, t
           if(x>y) then
                t = y
                y = x
                x = t
           endif
       end




Это сообщение отредактировал(а) FCM - 25.10.2010, 16:30
PM MAIL   Вверх
TepH
Дата 25.10.2010, 16:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 12
Регистрация: 24.10.2010

Репутация: нет
Всего: нет



Хм. Заработало, вроде как... А я был близок к разгадке, когда искал, как подправить. 

А, дошло. "a" всегда меньшее, "с" - большее.
Поэтому в облегчённом и равенство а=в и в=с (правда бежать пора, потом посмотрю)
Спасибо.
Вы тут писали, пока, видимо, не исправили, что мне не стоит так, что я не знаю куда сунуться,  раз учусь в техническом. Пожалуй Вы правы.
Я в технаре учился, там, в общем-то железятник, хоть мы немного проходили qbasic  и Turbo Pascal, но там как-то не так всё... И то, почти только ознакомительно.
Поэтому довольно сложно не зная сразу программы писать, пусть и простейшие...
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Fortran | Следующая тема »


 




[ Время генерации скрипта: 0.1033 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.