OberonCore

Библиотека  Wiki  Форум  BlackBox  Компоненты  Проекты
Текущее время: Воскресенье, 19 Май, 2024 00:32

Часовой пояс: UTC + 3 часа




Начать новую тему Ответить на тему  [ Сообщений: 17 ] 
Автор Сообщение
 Заголовок сообщения: Странная ошибка
СообщениеДобавлено: Суббота, 04 Май, 2024 06:44 

Зарегистрирован: Воскресенье, 06 Август, 2017 19:33
Сообщения: 84
Почему-то при выполнении
Код:
StdLog.Bool ((0.12 * Math.IntPower (10, 2)) = (0.12 * Math.IntPower (10, 2)));
выдаёт FALSE.
у меня BB 1.7.1


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Странная ошибка
СообщениеДобавлено: Суббота, 04 Май, 2024 09:26 
Аватара пользователя

Зарегистрирован: Четверг, 08 Октябрь, 2009 15:00
Сообщения: 3784
Пока не вник детально, но сразу скажу, что сравнивать действительные числа нельзя. Их можно только вычитать и смотреть отличается ли разница на некоторый eps (очень малую величину).

StdLog.Bool(ABS((0.12 * Math.IntPower (10, 2)) - (0.12 * Math.IntPower (10, 2))) < 10.0E-10); StdLog.Ln;


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Странная ошибка
СообщениеДобавлено: Суббота, 04 Май, 2024 09:31 
Аватара пользователя

Зарегистрирован: Четверг, 08 Октябрь, 2009 15:00
Сообщения: 3784
Заметил, что ABS в объявлении о языке не определён для REAL, но тем не менее работает...


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Странная ошибка
СообщениеДобавлено: Суббота, 04 Май, 2024 15:20 

Зарегистрирован: Воскресенье, 06 Август, 2017 19:33
Сообщения: 84
Цитата:
скажу, что сравнивать действительные числа нельзя

А почему? Загнал одно число в один регистр, другое - в другой и сравнил их побитово.
Цитата:
смотреть отличается ли разница на некоторый eps

Но это же тоже сравнение.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Странная ошибка
СообщениеДобавлено: Суббота, 04 Май, 2024 16:18 

Зарегистрирован: Воскресенье, 06 Август, 2017 19:33
Сообщения: 84
Как мне кажется, раз и левая и правая части равенства выполняются по одному и тому-же алгоритму, то где-то в Math к числу "примешивается что-то из вне". Может где-то там не выставляется исходное значение переменной перед её использованием.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Странная ошибка
СообщениеДобавлено: Суббота, 04 Май, 2024 16:41 

Зарегистрирован: Воскресенье, 06 Август, 2017 19:33
Сообщения: 84
У меня ещё вот какой вопрос: сколько бит отводится под мантиссу и сколько под экспоненту в типе REAL?


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Странная ошибка
СообщениеДобавлено: Суббота, 04 Май, 2024 20:28 
Администратор

Зарегистрирован: Вторник, 15 Ноябрь, 2005 01:14
Сообщения: 4696
Откуда: Россия, Орёл
Александр К писал(а):
У меня ещё вот какой вопрос: сколько бит отводится под мантиссу и сколько под экспоненту в типе REAL?

IEEE 754 64 бит (см. например, https://ru.wikipedia.org/wiki/IEEE_754-2008 )


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Странная ошибка
СообщениеДобавлено: Воскресенье, 05 Май, 2024 19:34 
Аватара пользователя

Зарегистрирован: Четверг, 08 Октябрь, 2009 15:00
Сообщения: 3784
Александр К писал(а):
Цитата:
смотреть отличается ли разница на некоторый eps

Но это же тоже сравнение.

Сравнение, но уже правильное


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Странная ошибка
СообщениеДобавлено: Понедельник, 06 Май, 2024 01:54 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1174
тем не менее, это баг. потому что результат обоих выражений должен быть bit-to-bit exact. и, как полагается, в двух нижепроцитированых случаях получаем ожидаемое "$TRUE":
Код:
PROCEDURE Test02*;
VAR
   a, b: REAL;
   v: BOOLEAN;
BEGIN
   a := 0.12 * Math.IntPower (10, 2);
   b := 0.12 * Math.IntPower (10, 2);
   v := (a = b);
   StdLog.Bool(v):Ln;
END Test02;

PROCEDURE Boo (a, b: REAL): BOOLEAN;
BEGIN
   RETURN a = b;
END Boo;

PROCEDURE Test03*;
VAR
   v: BOOLEAN;
BEGIN
   v := Boo(0.12 * Math.IntPower (10, 2), (0.12 * Math.IntPower (10, 2)));
   StdLog.Bool(v):Ln;
END Test03;


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Странная ошибка
СообщениеДобавлено: Понедельник, 06 Май, 2024 02:25 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1174
вообще, мне сейчас вникать не особо есть возможность, но есть мнение, что виноват вот этот код:
Код:
0000009BH:   DC 0D 7C 00 00 64    FMUL   DOUBLE [1677721724]
000000A1H:   DC 1C 24    FCOMP   DOUBLE [ESP]

мы здесь видим что? а видим мы сравнение 80-bit real (внутреннего формата FPU) — и округлённого до 64 бит результата предыдущего выражения. в тех же случаях, которые я процитировал, оба результата округляются (потому что сохраняются в память) — и бага нет.

как вариант — насильно перевести FPU в режим 64-битных вычислений, например. или просто смириться, запомнить, что результат вычислений с плавающей точкой имеет нестабильный ULP, и писать код с учётом этого.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Странная ошибка
СообщениеДобавлено: Понедельник, 06 Май, 2024 10:17 
Аватара пользователя

Зарегистрирован: Четверг, 08 Октябрь, 2009 15:00
Сообщения: 3784
arisu писал(а):
как вариант — насильно перевести FPU в режим 64-битных вычислений, например. или просто смириться, запомнить, что результат вычислений с плавающей точкой имеет нестабильный ULP, и писать код с учётом этого.

Думаю, что это единственно верный вариант действий, так как это формирует правильную привычку, которая сэкономит кучу времени и возможно даже сохранит кому-то жизни в перспективе. Не факт ведь, что код будет выполнятся именно на таких машинных инструкциях когда-то. Если даже сейчас тут "подпилить" компилятор, чтобы он делал какие-то симметричные округления, нет гарантии, что на другом процессоре потом это будет также выполнятся.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Странная ошибка
СообщениеДобавлено: Понедельник, 06 Май, 2024 15:11 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1174
проблема, однако же, в том, что всякие разные внешние библиотеки, например, тоже любят FPU трогать лапами немытыми. приснопамятный DirectX, например, вообще любил перевести его в одинарную точность и так оставить. а что, хватит всем. другие же библиотеки могут ожидать конкретных режимов, установленых их любимым компилятором си — или тупо форсить его обратно.

это и сейчас проблема, на самом деле. если я верню помню, именно поэтому стандартный CP2 заново инициализирует FPU после каждого обращения к внешней библиотеке (что я в LC отрезал). тормоза-с адовые.

короче, красивого и правильного решения у проблемы FPU нет. можно, конечно, сменить слово инициализации (кажется, где-то в Kernel; и не забыть проверить CP2 — там, по-моему, тоже забито волшебное число) — и это проблему спрячет.

более лучший вариант решения — перестать использовать FPU, и обучить кодоген использовать SSE.

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

и в любом случае утешиться тем, что FPU — это была общая боль, не специфичная для оберона. компиляторы си тоже насильно скидывали результат в память, чтобы округлить, например.

ещё хороший вариант — последовать заветам Чака Мура: забить на floating point и использовать fixed point. но ни в коем случае не с LONGINT, потому что для лонгинтов CP2 использует FPU. floating point is overrated.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Странная ошибка
СообщениеДобавлено: Понедельник, 06 Май, 2024 15:21 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1174
Иван Денисов писал(а):
нет гарантии, что на другом процессоре потом это будет также выполнятся.

а вот этому никакие игры с FPU не помогут. IEEE требует стабильный результат, не более. разница в ULP на разных железных/программных реализациях допустима, например, если она стабильна. так что вычисления с floating point в принципе непортабельны между разным железом (и даже не обязаны быть переносимы между разными ревизиями одного и того же). я уж не говорю про вычисления квадратных корней, всяких там трансцендентальных функций и других страшных гитик. или вот кто-то (да, я смотрю на тебя, SSE!) может криво реализовать субнормалы, например.

в общем, в mission-critical вычислениях надо или жёстко привязаться к строго определённому железу, или не использовать floating point вообще. поэтому проблема переносимости подобных вычислений значения не имеет, я считаю.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Странная ошибка
СообщениеДобавлено: Понедельник, 06 Май, 2024 16:02 
Аватара пользователя

Зарегистрирован: Четверг, 08 Октябрь, 2009 15:00
Сообщения: 3784
Да, поэтому и говорю, что "запомнить, что результат вычислений с плавающей точкой имеет нестабильный ULP, и писать код с учётом этого" — это вот стратегически правильно, а остальное "от лукавого" ))

Код:
equal := ABS(real1 - real2) < eps;

вот такой код переносим


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Странная ошибка
СообщениеДобавлено: Понедельник, 06 Май, 2024 16:09 
Аватара пользователя

Зарегистрирован: Четверг, 08 Октябрь, 2009 15:00
Сообщения: 3784
arisu писал(а):
это и сейчас проблема, на самом деле. если я верню помню, именно поэтому стандартный CP2 заново инициализирует FPU после каждого обращения к внешней библиотеке (что я в LC отрезал). тормоза-с адовые.

а в каком коммите это реализовано? это была бы классная опция компилятора, изучить было бы любопытно на каком-то примере


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Странная ошибка
СообщениеДобавлено: Вторник, 07 Май, 2024 01:03 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1174
Иван Денисов писал(а):
arisu писал(а):
это и сейчас проблема, на самом деле. если я верню помню, именно поэтому стандартный CP2 заново инициализирует FPU после каждого обращения к внешней библиотеке (что я в LC отрезал). тормоза-с адовые.

а в каком коммите это реализовано? это была бы классная опция компилятора, изучить было бы любопытно на каком-то примере
не помню, но никакой ракетной науки, право слово.

в DevCPC486, процедура "Enter". там в конце написано: "IF useFpu THEN InitFpu END". что, в общем, верное и надёжное решение, но я его посчитал совершенно излишним, и просто это закомментарил.

и заодно наврал: реинит делается вообще при каждом входе в процедуру, которая использует FPU. омики серьёзно к этим делам относилиь, да.


Вернуться к началу
 Профиль  
 
 Заголовок сообщения: Re: Странная ошибка
СообщениеДобавлено: Вторник, 07 Май, 2024 01:13 

Зарегистрирован: Воскресенье, 25 Декабрь, 2022 23:14
Сообщения: 1174
сравнение с фиксированым эпсилоном, кстати, не совсем верное. плавающие распределены неравномерно, и эпсилон часто надо динамически выбирать в зависимости от значений и цели, а не просто прибивать гвоздями.

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

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

флоаты — это СЛОЖНА! ;-) если можно обойтись без них — лучше обойтись. вон, в ящике предпочли для устройство-независимых координат fixed point, хотя могли бы и floating.


Вернуться к началу
 Профиль  
 
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 17 ] 

Часовой пояс: UTC + 3 часа


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

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


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Вся информация, размещаемая участниками на конференции (тексты сообщений, вложения и пр.) © 2005-2024, участники конференции «OberonCore», если специально не оговорено иное.
Администрация не несет ответственности за мнения, стиль и достоверность высказываний участников, равно как и за безопасность материалов, предоставляемых участниками во вложениях.
Без разрешения участников и ссылки на конференцию «OberonCore» любое воспроизведение и/или копирование высказываний полностью и/или по частям запрещено.
Powered by phpBB® Forum Software © phpBB Group
Русская поддержка phpBB