OberonCore
https://forum.oberoncore.ru/

Сравнение вещественных чисел
https://forum.oberoncore.ru/viewtopic.php?f=29&t=3327
Страница 1 из 4

Автор:  igor [ Воскресенье, 13 Март, 2011 12:36 ]
Заголовок сообщения:  Сравнение вещественных чисел

Предлагаю к обсуждению такой код:
Код:
MODULE TempTest;

IMPORT Log := StdLog;

PROCEDURE Do*;
VAR a: SHORTREAL; b, c: REAL;
BEGIN
   Log.Ln;
   a := 0.1;
   b := 0.1;
   c := a;
   IF a = b THEN Log.String("a = b") ELSE Log.String("a # b") END;
   Log.Ln;
   IF a = c THEN Log.String("a = c") ELSE Log.String("a # c") END;
   Log.Ln;
END Do;

END TempTest.

Этот код даёт такой результат:
Код:
a # b
a = c


Возникает два вопроса:
1. Почему первый результат отрицательный?
2. Почему первый и второй результаты различны?

Собственно, прямые ответы на эти вопросы нам известны и потому не интересны.
Но должно ли так быть? Разве ЯВУ не должен нас изолировать от внутренних форматов хранения вещественных чисел (IEEE Standart 754, если не ошибаюсь)?

Замечу, что проблема касается всех ЯВУ. КП здесь использован только для примера.

Замечу также, что проблема не "высосана из пальца". Мне в таких случаях приходилось использовать доверительные интервалы, и вместо точного сравнения проверять попадание в этот интервал. Но постоянное использование этого приёма утомляет. Хотелось бы решить проблему на уровне языка.

Автор:  Info21 [ Воскресенье, 13 Март, 2011 13:36 ]
Заголовок сообщения:  Re: Сравнение вещественных чисел

igor писал(а):
Хотелось бы решить проблему на уровне языка.
Ха ха ха.

Подозреваю, что вернее всего идти по пути интервальной арифметики.

Автор:  Иван Денисов [ Воскресенье, 13 Март, 2011 13:48 ]
Заголовок сообщения:  Re: Сравнение вещественных чисел

http://www.php.net/manual/ru/language.types.float.php
Цитата:
Числа с плавающей точкой имеют ограниченную точность. Хотя это зависит от операционной системы, в PHP обычно используется формат двойной точности IEEE 754, дающий максимальную относительную ошибку округления порядка 1.11e-16. Неэлементарные арифметические операции могут давать большие ошибки, и, разумеется, необходимо принимать во внимание разрастание ошибок при совместном использовании нескольких операции.

Кроме того, рациональные числа, которые могут быть точно представлены в виде чисел с плавающей точкой с основанием 10, например, 0.1 или 0.7, не имеют точного внутреннего представления в качестве чисел с плавающей точкой с основанием 2, вне зависимости от размера мантиссы. Поэтому они и не могут быть преобразованы в их внутреннюю двоичную форму без небольшой потери точности. Это может привести к неожиданным результатам: например, floor((0.1+0.7)*10) скорее всего вернет 7 вместо ожидаемого 8, так как результат внутреннего представления будет чем-то вроде 7.9999999999999991118....

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


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

Автор:  Сергей Прохоренко [ Воскресенье, 13 Март, 2011 18:06 ]
Заголовок сообщения:  Re: Сравнение вещественных чисел

Проблема решается просто: в языке должно быть запрещено сравнение вещественных чисел на равенство. :D

Автор:  igor [ Воскресенье, 13 Март, 2011 18:13 ]
Заголовок сообщения:  Re: Сравнение вещественных чисел

Info21 писал(а):
Подозреваю, что вернее всего идти по пути интервальной арифметики.

Видимо, ничего другого не остаётся. Сложность однако состоит в том, каким образом определять оптимальные интервалы. Да ещё нужно следить за тем, чтобы не нарушить свойство монотонности числовой прямой.

По поводу "ха-ха-ха" абсолютно согласен с Вами :) . Наивно полагать, что великие умы не знакомы с этой проблемой. И раз эта проблема до сих пор не решена, то моё сообщение выглядит как попытка бросить им вызов. На самом деле никакой это не вызов, просто я оставляю за собой право рассмотреть проблематику этого вопроса.

Автор:  igor [ Воскресенье, 13 Март, 2011 18:22 ]
Заголовок сообщения:  Re: Сравнение вещественных чисел

divan писал(а):
Так что на уровне языка это неразрешимый вопрос
Звучит как "вертикальный полёт не возможен" :)

divan писал(а):
ну нельзя представить 0.1 в двоичной форме без потери точности.
Так ведь никто и не ставит такой цели :!:

divan писал(а):
Интересно было бы узнать вашу задачу.
Не, не интересно. Если возникают такие проблемы, то я их успешно решаю. А хотелось бы вообще избежать возникновения таких проблем. :wink: То есть хотелось бы перенести решение с уровня моей задачи на уровень языка.

Автор:  igor [ Воскресенье, 13 Март, 2011 18:25 ]
Заголовок сообщения:  Re: Сравнение вещественных чисел

Сергей Прохоренко писал(а):
Проблема решается просто: в языке должно быть запрещено сравнение вещественных чисел на равенство. :D
Ну, да. Чтобы не было больных и несчастных, нужно расстрелять всех больных и несчастных. И тогда все будут здоровы и счастливы.

Автор:  Info21 [ Воскресенье, 13 Март, 2011 20:03 ]
Заголовок сообщения:  Re: Сравнение вещественных чисел

Сергей Прохоренко писал(а):
Проблема решается просто: в языке должно быть запрещено сравнение вещественных чисел на равенство. :D
А неплохое решение.

Автор:  Александр Ильин [ Воскресенье, 13 Март, 2011 20:04 ]
Заголовок сообщения:  Re: Сравнение вещественных чисел

Info21 писал(а):
Сергей Прохоренко писал(а):
Проблема решается просто: в языке должно быть запрещено сравнение вещественных чисел на равенство. :D
А неплохое решение.
Поправка: вещественных разного размера. Проблема ведь в этом.

Автор:  Валерий Лаптев [ Воскресенье, 13 Март, 2011 20:43 ]
Заголовок сообщения:  Re: Сравнение вещественных чисел

1. Если говорить об обучении, то ни о каких размерах начинающему знать ни к чему.
2. Можно запретить сравнение вещественных разного размера.
3. Можно запретить присваивание вещественных разного размера в обе стороны. Я так понимаю, что либо нам нужна точность, либо мы экономим память. Зачем нам два размера в одной программе?
4. Если сравнения на равенство чисел разного размера разрешены, тогда должно быть преобразование типа, в точности приводящее большую мантиссу в соответствующему значению малого размера. Проблема же в хвостике - паре последних разрядов.

Автор:  Сергей Прохоренко [ Воскресенье, 13 Март, 2011 20:43 ]
Заголовок сообщения:  Re: Сравнение вещественных чисел

Александр Ильин писал(а):
Info21 писал(а):
Сергей Прохоренко писал(а):
Проблема решается просто: в языке должно быть запрещено сравнение вещественных чисел на равенство. :D
А неплохое решение.
Поправка: вещественных разного размера. Проблема ведь в этом.


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

Автор:  Info21 [ Воскресенье, 13 Март, 2011 21:39 ]
Заголовок сообщения:  Re: Сравнение вещественных чисел

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

Автор:  igor [ Понедельник, 14 Март, 2011 06:13 ]
Заголовок сообщения:  Re: Сравнение вещественных чисел

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

Автор:  igor [ Понедельник, 14 Март, 2011 06:24 ]
Заголовок сообщения:  Re: Сравнение вещественных чисел

Валерий Лаптев писал(а):
4. Если сравнения на равенство чисел разного размера разрешены, тогда должно быть преобразование типа, в точности приводящее большую мантиссу в соответствующему значению малого размера.
Интересная мысль.

PS: Вообще я не сторонник решения проблем запретами, но признаю что частенько таких решений не избежать

Автор:  igor [ Понедельник, 14 Март, 2011 06:27 ]
Заголовок сообщения:  Re: Сравнение вещественных чисел

Info21 писал(а):
Сергей Прохоренко писал(а):
Проблема решается просто: в языке должно быть запрещено сравнение вещественных чисел на равенство. :D
А неплохое решение.

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

А что вы можете предложить взамен?

Автор:  Info21 [ Понедельник, 14 Март, 2011 12:27 ]
Заголовок сообщения:  Re: Сравнение вещественных чисел

igor писал(а):
Info21 писал(а):
Сергей Прохоренко писал(а):
Проблема решается просто: в языке должно быть запрещено сравнение вещественных чисел на равенство. :D
А неплохое решение.

Info21 писал(а):
Сергей Прохоренко писал(а):
Думаю, что запрет должен касаться вещественных одинакового размера тоже
Да.
А что вы можете предложить взамен?
Ну как. Следить за ошибками и неравенства.
Floating-point на кривой кобыле не объехать.

Автор:  Ярослав Романченко [ Понедельник, 14 Март, 2011 12:31 ]
Заголовок сообщения:  Re: Сравнение вещественных чисел

igor писал(а):
Тогда уж лучше было бы исключить все вещественные типы, кроме одного - самого точного.
С менее точными типами вычисления производятся быстрее, и не всегда нужна самая высокая точность.

Автор:  albobin [ Понедельник, 14 Март, 2011 12:55 ]
Заголовок сообщения:  Re: Сравнение вещественных чисел

А если число1 и не больше и не меньше числа2 , то что тогда? Равно?

Автор:  igor [ Понедельник, 14 Март, 2011 13:09 ]
Заголовок сообщения:  Re: Сравнение вещественных чисел

Info21 писал(а):
Следить за ошибками и неравенства.
То есть вместо сравнения на равенство использовать сравнение на больше или меньше? Ну, это вроде ничего не меняет. Результату такого сравнения мы по прежнему не можем доверять.

Info21 писал(а):
Floating-point на кривой кобыле не объехать.
Где б её взять только, прямую кобылу. :)

Автор:  igor [ Понедельник, 14 Март, 2011 13:53 ]
Заголовок сообщения:  Re: Сравнение вещественных чисел

Суть проблемы, вроде как, состоит в том, что три дискретных числовых оси не совпадают. Эти дискретные числовые оси соответствуют десятичному представлению и двум двоичным (SHORTREAL и REAL).

Парочка замечаний:
1. Так как мы не можем в исходном тексте записать число из бесконечного числа цифр, то мы никогда не имеем дело с непрерывной числовой осью.
2. Результаты вычислений всегда отоборажаются на дискретную числовую ось, соответствующую двоичному представлению. А непосредственные вещественные константы - на дискретную ось, соответсвующую десятичному представлению.

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

Попробуем мысленно совместить все три оси. Дискретные числовые значения, соответствующие разным представлениям, будут расположены на совмещённой оси вперемежку, в основом не совпадая друг с другом. К тому же интервалы между числовыми значениями также будут различными.

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

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

То, что я изложил - не решение, а скорее постановка задачи. Боюсь, что эта задача вообще не имеет эффективного решения.

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