OberonCore
https://forum.oberoncore.ru/

Странная ошибка
https://forum.oberoncore.ru/viewtopic.php?f=23&t=6980
Страница 1 из 2

Автор:  Александр К [ Суббота, 04 Май, 2024 06:44 ]
Заголовок сообщения:  Странная ошибка

Почему-то при выполнении
Код:
StdLog.Bool ((0.12 * Math.IntPower (10, 2)) = (0.12 * Math.IntPower (10, 2)));
выдаёт FALSE.
у меня BB 1.7.1

Автор:  Иван Денисов [ Суббота, 04 Май, 2024 09:26 ]
Заголовок сообщения:  Re: Странная ошибка

Пока не вник детально, но сразу скажу, что сравнивать действительные числа нельзя. Их можно только вычитать и смотреть отличается ли разница на некоторый eps (очень малую величину).

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

Автор:  Иван Денисов [ Суббота, 04 Май, 2024 09:31 ]
Заголовок сообщения:  Re: Странная ошибка

Заметил, что ABS в объявлении о языке не определён для REAL, но тем не менее работает...

Автор:  Александр К [ Суббота, 04 Май, 2024 15:20 ]
Заголовок сообщения:  Re: Странная ошибка

Цитата:
скажу, что сравнивать действительные числа нельзя

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

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

Автор:  Александр К [ Суббота, 04 Май, 2024 16:18 ]
Заголовок сообщения:  Re: Странная ошибка

Как мне кажется, раз и левая и правая части равенства выполняются по одному и тому-же алгоритму, то где-то в Math к числу "примешивается что-то из вне". Может где-то там не выставляется исходное значение переменной перед её использованием.

Автор:  Александр К [ Суббота, 04 Май, 2024 16:41 ]
Заголовок сообщения:  Re: Странная ошибка

У меня ещё вот какой вопрос: сколько бит отводится под мантиссу и сколько под экспоненту в типе REAL?

Автор:  Борис Рюмшин [ Суббота, 04 Май, 2024 20:28 ]
Заголовок сообщения:  Re: Странная ошибка

Александр К писал(а):
У меня ещё вот какой вопрос: сколько бит отводится под мантиссу и сколько под экспоненту в типе REAL?

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

Автор:  Иван Денисов [ Воскресенье, 05 Май, 2024 19:34 ]
Заголовок сообщения:  Re: Странная ошибка

Александр К писал(а):
Цитата:
смотреть отличается ли разница на некоторый eps

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

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

Автор:  arisu [ Понедельник, 06 Май, 2024 01:54 ]
Заголовок сообщения:  Re: Странная ошибка

тем не менее, это баг. потому что результат обоих выражений должен быть 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;

Автор:  arisu [ Понедельник, 06 Май, 2024 02:25 ]
Заголовок сообщения:  Re: Странная ошибка

вообще, мне сейчас вникать не особо есть возможность, но есть мнение, что виноват вот этот код:
Код:
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, и писать код с учётом этого.

Автор:  Иван Денисов [ Понедельник, 06 Май, 2024 10:17 ]
Заголовок сообщения:  Re: Странная ошибка

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

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

Автор:  arisu [ Понедельник, 06 Май, 2024 15:11 ]
Заголовок сообщения:  Re: Странная ошибка

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

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

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

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

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

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

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

Автор:  arisu [ Понедельник, 06 Май, 2024 15:21 ]
Заголовок сообщения:  Re: Странная ошибка

Иван Денисов писал(а):
нет гарантии, что на другом процессоре потом это будет также выполнятся.

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

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

Автор:  Иван Денисов [ Понедельник, 06 Май, 2024 16:02 ]
Заголовок сообщения:  Re: Странная ошибка

Да, поэтому и говорю, что "запомнить, что результат вычислений с плавающей точкой имеет нестабильный ULP, и писать код с учётом этого" — это вот стратегически правильно, а остальное "от лукавого" ))

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

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

Автор:  Иван Денисов [ Понедельник, 06 Май, 2024 16:09 ]
Заголовок сообщения:  Re: Странная ошибка

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

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

Автор:  arisu [ Вторник, 07 Май, 2024 01:03 ]
Заголовок сообщения:  Re: Странная ошибка

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

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

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

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

Автор:  arisu [ Вторник, 07 Май, 2024 01:13 ]
Заголовок сообщения:  Re: Странная ошибка

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

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

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

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

Автор:  Александр К [ Вторник, 17 Сентябрь, 2024 02:49 ]
Заголовок сообщения:  Re: Странная ошибка

А зачем число округляется при присвоении его переменной?

Автор:  arisu [ Вторник, 17 Сентябрь, 2024 02:59 ]
Заголовок сообщения:  Re: Странная ошибка

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

Автор:  Александр К [ Среда, 18 Сентябрь, 2024 03:12 ]
Заголовок сообщения:  Re: Странная ошибка

А почему тогда тип REAL не делают размером с внутреннее представление математического процессора?

Страница 1 из 2 Часовой пояс: UTC + 3 часа
Powered by phpBB® Forum Software © phpBB Group
https://www.phpbb.com/