SIGFPE Arccos на sqrt, в процедуре из 2-х строк, что делать?

Общие вопросы программирования, алгоритмы и т.п.

Модератор: Модераторы

SIGFPE Arccos на sqrt, в процедуре из 2-х строк, что делать?

Сообщение max » 24.10.2019 22:05:18

Всем доброго времени суток!

Пустая форма на ней только кнопка и обработчик по клику. Win32.
На строке e:= sqrt(e); падает с SIGFPE. Как это можно и нужно решать?

Код: Выделить всё
unit Unit1;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, math;

type

  { TForm1 }

  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private

  public

  end;

var
  Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

procedure TForm1.Button1Click(Sender: TObject);
var e:ValReal;
begin
  e:=-1.42177208859313605512E+0018;
  e:= sqrt(e);
end;

end.     
Последний раз редактировалось max 24.10.2019 23:28:36, всего редактировалось 1 раз.
max
новенький
 
Сообщения: 18
Зарегистрирован: 10.12.2018 17:13:22

Re: SIGFPE на sqrt, в процедуре из "2-х" строк, что делать?

Сообщение Снег Север » 24.10.2019 22:43:37

max, интересно, а что должно еще давать извлечение квадратного корня из отрицательного числа? :?
Аватара пользователя
Снег Север
долгожитель
 
Сообщения: 2233
Зарегистрирован: 27.11.2007 16:14:47

Re: SIGFPE на sqrt, в процедуре из "2-х" строк, что делать?

Сообщение max » 24.10.2019 22:48:49

тоже падало sqrt(abs(e));

Добавлено спустя 4 минуты 9 секунд:
Хотя вру, падало на Arccos(abs(x));

А sqrt появился когда я разобрал функцию Arccos на этапы и нашёл, там, что падает именно на sqrt(). И если Arccos дополнить sqrt(abs(e));, то падать действительно перестаёт.

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

Добавлено спустя 13 минут 43 секунды:
Вот воспроизведение ошибки, на Arccos:
Код: Выделить всё
procedure TForm1.Button2Click(Sender: TObject);
var e:extended;
begin
  e := 1.19238084880340813706E+0009;
  Arccos(e);
end;     


Проверяйте если баг, то значит баг.
max
новенький
 
Сообщения: 18
Зарегистрирован: 10.12.2018 17:13:22

Re: SIGFPE Arccos на sqrt, в процедуре из 2-х строк, что дел

Сообщение Vadim » 25.10.2019 04:09:15

max писал(а):Проверяйте если баг, то значит баг.

Информация к размышлению... ;-)
Screenshot_20191025_070439.png
Vadim
долгожитель
 
Сообщения: 3800
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: SIGFPE Arccos на sqrt, в процедуре из 2-х строк, что дел

Сообщение Снег Север » 25.10.2019 07:40:59

max, а если мозги включить? Диапазон допустимых значений аргумента для арккосинуса (и арксинуса) - от -1 до 1. А вы что туда суете?
Аватара пользователя
Снег Север
долгожитель
 
Сообщения: 2233
Зарегистрирован: 27.11.2007 16:14:47

Re: SIGFPE Arccos на sqrt, в процедуре из 2-х строк, что дел

Сообщение max » 25.10.2019 08:57:40

Vadim писал(а):Информация к размышлению...

Оно валится только когда через переменную значение ей передаётся.
Литералы почему-то вычисляет без ошибок.
И только при значениях из переменных делает SIGFPE.
только вот так:
e := 1.19238084880340813706E+0009; // вначале в переменную
Arccos(e); // <== а потом наблюдаем SIGFPE

Снег Север писал(а):а если мозги включить? Диапазон допустимых значений аргумента для арккосинуса (и арксинуса) - от -1 до 1. А вы что туда суете?

Я делаю всё по формулам, которые в том числе есть даже в учебнике по программированию: http://www.freepascal.ru/download/book/ ... azarus.pdf.
Вот например: arccos ( ( sqr ( b)+sqr ( c)−sqr ( a ) ) / 2 / b/ c ) ; И согласно листингу, в программу передаются значения реальных треугольников, которые можно построить. Но она SIGFPE, именно из-за отрицательного числа в arccos на sqrt. Как только добавил abs в функцию arccos -- перестала делать SIGFPE и возвращает верные значения.

Добавлено спустя 21 минуту 1 секунду:
Re: SIGFPE Arccos на sqrt, в процедуре из 2-х строк, что делать?
Снег Север писал(а):Диапазон допустимых значений аргумента для арккосинуса (и арксинуса) - от -1 до 1. А вы что туда суете?

И кстати, согласно листингу в arccos -- подаются верные значения от -1 до 1, но в arccos -- они превращаются в отрицательное и делают SIGFPE на sqrt.
max
новенький
 
Сообщения: 18
Зарегистрирован: 10.12.2018 17:13:22

Re: SIGFPE Arccos на sqrt, в процедуре из 2-х строк, что дел

Сообщение Vadim » 25.10.2019 09:20:24

max писал(а):Я делаю всё по формулам, которые в том числе есть даже в учебнике по программированию

А Вы, простите, в каком классе учитесь?
Видите ли, я специально вывесил этот рисунок чтобы показать - в арккосинус можно передавать любые значения только в том случае, если он работает с комплексными числами. А FPC, как Вы успели убедиться, с комплексными числами не работает, такого встроенного типа здесь нет, в отличие от Фортрана. Поэтому то, что Вы получаете - это не баг, а именно то, что должно быть. Если не верите Снег Северу, который сказал Вам чистую правду, то загляните хотя бы в Википедию...
Изображение
Vadim
долгожитель
 
Сообщения: 3800
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: SIGFPE Arccos на sqrt, в процедуре из 2-х строк, что дел

Сообщение max » 25.10.2019 09:27:40

Vadim писал(а):А Вы, простите, в каком классе учитесь?

Я просто на автомате показал число в примере, т.к. искал сбой.
Вот листинг, значений. Слева значения после FloatToStrF. Справа те что передаются в arccos и вызывают SIGFPE на sqrt.
Код: Выделить всё
0.96709963 |  9.67099629724473999802E-0001
0.76464849 |  7.64648488061222847954E-0001
-0.96591816 | -9.65918157142044800335E-0001
-0.96591811 | -9.65918114119857906818E-0001
-0.96591807 | -9.65918070734634307028E-0001
-0.96591803 | -9.65918026982293063444E-0001
-0.96591798 | -9.65917982858670164862E-0001
-0.96591794 | -9.65917938359559623621E-0001
-0.96591789 | -9.65917893480682647662E-0001
-0.96591785 | -9.65917848217709613251E-0001
-0.96591780 | -9.65917802566246319455E-0001
-0.96591776 | -9.65917756521828489832E-0001
-0.96591771 | -9.65917710079940992679E-0001
-0.96591766 | -9.65917663235989060340E-0001
-0.96591762 | -9.65917615985321378544E-0001
-0.96591757 | -9.65917568323217467098E-0001
-0.96591752 | -9.65917520244882528522E-0001
-0.96591747 | -9.65917471745459349389E-0001
-0.96591742 | -9.65917422820017431524E-0001
-0.96591737 | -9.65917373463545966697E-0001
-0.96591732 | -9.65917323670978226027E-0001
-0.96591727 | -9.65917273437149094106E-0001
-0.96591722 | -9.65917222756836535186E-0001
-0.96591717 | -9.65917171624735930273E-0001
-0.96591712 | -9.65917120035454568729E-0001
-0.96591707 | -9.65917067983526556431E-0001
-0.96591702 | -9.65917015463415818311E-0001
-0.96591696 | -9.65916962469470316880E-0001
-0.96591691 | -9.65916908995990731621E-0001
-0.96591686 | -9.65916855037164697026E-0001
-0.96591680 | -9.65916800587104537113E-0001
-0.96591675 | -9.65916745639830242806E-0001
-0.96591669 | -9.65916690189262999516E-0001
-0.96591663 | -9.65916634229247530053E-0001
-0.96591658 | -9.65916577753515515927E-0001
-0.96591652 | -9.65916520755715780390E-0001
-0.96591646 | -9.65916463229391466746E-0001
-0.96591641 | -9.65916405167989684767E-0001
-0.96591635 | -9.65916346564851618374E-0001
-0.96591629 | -9.65916287413217771558E-0001
-0.96591623 | -9.65916227706225123965E-0001
-0.96591617 | -9.65916167436894504558E-0001
-0.96591611 | -9.65916106598146325388E-0001
-0.96591605 | -9.65916045182781709167E-0001
-0.96591598 | -9.65915983183496159963E-0001
-0.96591592 | -9.65915920592859385122E-0001
-0.96591586 | -9.65915857403328321302E-0001
-0.96591579 | -9.65915793607235951851E-0001
-0.96591573 | -9.65915729196801381862E-0001
-0.96591566 | -9.65915664164102353705E-0001
-0.96591560 | -9.65915598501102897866E-0001
-0.96591553 | -9.65915532199633291796E-0001
-0.96591547 | -9.65915465251384596510E-0001
-0.96591540 | -9.65915397647917915562E-0001
-0.96591533 | -9.65915329380659663046E-0001
-0.96591526 | -9.65915260440886026491E-0001
-0.96591519 | -9.65915190819738133548E-0001
-0.96591512 | -9.65915120508204050928E-0001
-0.96591505 | -9.65915049497130702926E-0001
-0.96591498 | -9.65914977777202518768E-0001
-0.96591491 | -9.65914905338955621721E-0001
-0.96591483 | -9.65914832172767374790E-0001
-0.96591476 | -9.65914758268847901273E-0001
-0.96591468 | -9.65914683617247551398E-0001
-0.96591461 | -9.65914608207851946916E-0001
-0.96591453 | -9.65914532030361268778E-0001
-0.96591446 | -9.65914455074313025868E-0001
-0.96591438 | -9.65914377329061756461E-0001
-0.96591430 | -9.65914298783785346735E-0001
-0.96591422 | -9.65914219427452782750E-0001
-0.96591414 | -9.65914139248882018822E-0001
-0.96591406 | -9.65914058236653414434E-0001
-0.96591398 | -9.65913976379185492001E-0001
-0.96591389 | -9.65913893664666975988E-0001
-0.96591381 | -9.65913810081105676873E-0001
-0.96591373 | -9.65913725616272526744E-0001
-0.96591364 | -9.65913640257739235977E-0001
-0.96591355 | -9.65913553992854933227E-0001
-0.96591347 | -9.65913466808743412912E-0001
-0.96591338 | -9.65913378692295319092E-0001
-0.96591329 | -9.65913289630172971687E-0001
-0.96591320 | -9.65913199608791058620E-0001
-0.96591311 | -9.65913108614330570480E-0001
-0.96591302 | -9.65913016632715248444E-0001
-0.96591292 | -9.65912923649610480402E-0001
-0.96591283 | -9.65912829650432246109E-0001
-0.96591273 | -9.65912734620314248572E-0001
-0.96591264 | -9.65912638544132815129E-0001
-0.96591254 | -9.65912541406477226965E-0001
-0.96591244 | -9.65912443191647397938E-0001
-0.96591234 | -9.65912343883669555287E-0001
-0.96591224 | -9.65912243466251594845E-0001
-0.96591214 | -9.65912141922813421134E-0001
-0.96591204 | -9.65912039236448323205E-0001
-0.96591194 | -9.65911935389953225017E-0001
-0.96591183 | -9.65911830365771953422E-0001
-0.96591172 | -9.65911724146038846398E-0001
-0.96591162 | -9.65911616712536161310E-0001
-0.96591151 | -9.65911508046708898391E-0001
-0.96591140 | -9.65911398129619923824E-0001
-0.96591129 | -9.65911286942009391558E-0001
-0.96591117 | -9.65911174464196430837E-0001
-0.96591106 | -9.65911060676162819987E-0001
-0.96591095 | -9.65910945557469378117E-0001
-0.96591083 | -9.65910829087287921540E-0001
-0.96591071 | -9.65910711244386421532E-0001
-0.96591059 | -9.65910592007103451970E-0001
-0.96591047 | -9.65910471353358312521E-0001
-0.96591035 | -9.65910349260619899465E-0001
-0.96591023 | -9.65910225705926724950E-0001
-0.96591010 | -9.65910100665831530136E-0001
-0.96590997 | -9.65909974116440447997E-0001
-0.96590985 | -9.65909846033356800875E-0001
-0.96590972 | -9.65909716391708101399E-0001
-0.96590959 | -9.65909585166092020511E-0001
-0.96590945 | -9.65909452330611559745E-0001
-0.96590932 | -9.65909317858824468205E-0001
-0.96590918 | -9.65909181723743518930E-0001
-0.96590904 | -9.65909043897819018167E-0001
-0.96590890 | -9.65908904352948888337E-0001


И все значения от -1 до 1.
max
новенький
 
Сообщения: 18
Зарегистрирован: 10.12.2018 17:13:22

Re: SIGFPE Arccos на sqrt, в процедуре из 2-х строк, что дел

Сообщение Vadim » 25.10.2019 09:33:00

Ну вот, смотрите. Число -1 ещё вычисляется без всяких проблем, меньше - уже всё, трындец. Точно так же будет и с числом 1 - всё прекрасно, а больше 1 - уже трындец.
Код: Выделить всё
program arccosinus;
Uses math;

Begin
  WriteLn('Вычисляем арккосинус -1: ');
  WriteLn(arccos(-1):15:10);
  WriteLn;
  WriteLn;
  WriteLn('А теперь арккосинус -1.01 : ');
  WriteLn(arccos(-1.01):15:10);
End.

p2.png


Добавлено спустя 2 минуты 9 секунд:
Re: SIGFPE Arccos на sqrt, в процедуре из 2-х строк, что делать?
max писал(а):Я просто на автомате показал число

Нельзя показывать "просто", нужно показывать, чтобы был смысл. ;-)

Добавлено спустя 5 минут 50 секунд:
Re: SIGFPE Arccos на sqrt, в процедуре из 2-х строк, что делать?
max писал(а):Справа те что передаются в arccos и вызывают SIGFPE на sqrt.

А Вы не обманываете? :-)
p3.png
p3.png (6.98 КБ) Просмотров: 368

Скажите лучше - у Вашего компилятора какая битность?
Vadim
долгожитель
 
Сообщения: 3800
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: SIGFPE Arccos на sqrt, в процедуре из 2-х строк, что дел

Сообщение max » 25.10.2019 10:15:54

Vadim писал(а):Нельзя показывать "просто", нужно показывать, чтобы был смысл.

Показал-же листинг, значений от -1 до 1, при которых SIGFPE на arccos. Но воспроизвести ошибку из листинга -- мне не удалось. И более того, после попытки воспроизвести из листинга, оно, перестало выдавать SIGFPE. И heaptrc, всегда в норме. Так что, всё очень-очень плохо ((((((.

Добавлено спустя 1 минуту 24 секунды:
Re: SIGFPE Arccos на sqrt, в процедуре из 2-х строк, что делать?
Vadim писал(а):Скажите лучше - у Вашего компилятора какая битность?

Компилирую Win32 на и для Win64.

Добавлено спустя 4 минуты 18 секунд:
Re: SIGFPE Arccos на sqrt, в процедуре из 2-х строк, что делать?
Vadim писал(а):Скажите лучше - у Вашего компилятора какая битность?

Вы правильно мыслите, на счёт битности, т.к. там из-за какого-то переполнения, число превращалось в отрицательное и вызывало SIGFPE. Но теперь это вдруг почему-то исчезло. И я ничего не менял в программе. И это очень-очень плохо (((((( , т.к теперь непонятно как и почему.
max
новенький
 
Сообщения: 18
Зарегистрирован: 10.12.2018 17:13:22

Re: SIGFPE Arccos на sqrt, в процедуре из 2-х строк, что дел

Сообщение Vadim » 25.10.2019 10:23:51

max
Подойдём с другой стороны. А версия компилятора у Вас какая?
Vadim
долгожитель
 
Сообщения: 3800
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: SIGFPE Arccos на sqrt, в процедуре из 2-х строк, что дел

Сообщение max » 25.10.2019 10:26:19

Vadim писал(а):А версия компилятора у Вас какая?

3.0.4
max
новенький
 
Сообщения: 18
Зарегистрирован: 10.12.2018 17:13:22

Re: SIGFPE Arccos на sqrt, в процедуре из 2-х строк, что дел

Сообщение Vadim » 25.10.2019 10:28:06

max
На всякий пожарный. У компиляторов с разной битностью константы, которые Вы пишете в своей программе, будут разных типов. Почему так делают разработчики я не знаю, но на всякий случай это надо иметь в виду. Почитайте мою статейку по этому поводу:
http://freepascal.ru/article/freepascal/20181215220000/

У меня тоже версия 3.0.4. При правильных аргументах (т.е. от -1 до 1 включительно) ошибок нет...
Vadim
долгожитель
 
Сообщения: 3800
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

Re: SIGFPE Arccos на sqrt, в процедуре из 2-х строк, что дел

Сообщение max » 25.10.2019 11:10:14

Vadim писал(а):Почитайте мою статейку

Отличная статья, я читал её и раньше. И теперь перечитал. Спасибо, за статью.

Я до обращения на форум видел, что это происходило именно на уровне переменных, предполагал что, из-за переполнения знаков после запятой и даже в какой-то момент скармливал программе преднамеренно обрезанные до 8-ми знаков значения и SIGFPE исчезала. Потом начал копать внутрь. И благодаря Снег Север выяснил, что SIGFPE появлялась из-за отрицательного числа при sqrt в arccos. Отрицательное число в sqrt - предположительно и появлялось из-за переполнения знаков после запятой и это было постоянно. Но теперь, когда всё неожиданно перестало падать ................. найти причину стало невозможным. Так вот постольку поскольку я читал и Вашу статью и идентичное обсуждение на форуме, тоже про диверсии из-за типов - я везде использовал Extended и принудительно приводил к Extended. Но программа как-то в arccos этот Extended из-за переполнений превращала в отрицательное число. И мне вот тут сложно. С одной стороны помогало принудительное обрезание до 8 знаков после запятой. С другой стороны, помогала переделка функции arccos с вставкой туда abs чтобы в sqrt не подавалось отрицательное число. И число именно волшебно превращалось из положительного в отрицательное в функции arccos, выше по форуму, есть пример числа. Но теперь всё исчезло и я в глобальной печали, т.к. в любой момент оно может вернуться и оно похоже действительно появляется из-за переполнения знаков после запятой, что волшебно просто превращает число в отрицательное (значение сохраняется, т.к. abs это лечило и был верный результат). И это приводило к SIGFPE на sqrt.

Но как от этого защититься?
max
новенький
 
Сообщения: 18
Зарегистрирован: 10.12.2018 17:13:22

Re: SIGFPE Arccos на sqrt, в процедуре из 2-х строк, что дел

Сообщение Vadim » 25.10.2019 11:59:24

max
Ну, давайте начнём с верхнего уровня, т.е. с функции ArcCos(). Мы выяснили, что эта функция работает только в диапазоне данных от -1 до 1. Таким образом начать нужно с того, что перед её применением проверяем аргумент на вхождение в диапазон допустимых значений:
Код: Выделить всё
Var
  e: Double;

Begin
   . . .
   If (e >= -1.0) and (e <= 1.0) Then
     ArcCos(e)
   Else
     WriteLn('Я в шоке от такого числа: ', e);
   . . .
End;
Vadim
долгожитель
 
Сообщения: 3800
Зарегистрирован: 05.10.2006 08:52:59
Откуда: Красноярск

След.

Вернуться в Общее

Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 2

Рейтинг@Mail.ru