Автор Тема: Сравнение вещественных чисел  (Прочитано 28603 раз)

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Сравнение вещественных чисел
« : Март 14, 2011, 02:25:46 pm »
оригинальная ветка: http://forum.oberoncore.ru/viewtopic.php?p=61461#p61461

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

Суть проблемы не только в различии представления, но и вообще в потере точности при вычислениях. Те же самые грабли вы получите с одним и тем же вещественным типом, сравнив на равенство результаты 2/3 и 4/6. Так что идея запретить в языке сравнение вещественных типов не такая уж и плохая, учитывая что многие руководства по граблям так и пишут "не сравнивайте на равенство вещественные типы".

valexey

  • Administrator
  • Hero Member
  • *****
  • Сообщений: 1990
    • Просмотр профиля
Re:Сравнение вещественных чисел
« Ответ #1 : Март 14, 2011, 02:57:35 pm »
некоторые рефаловцы вообще считают что плавающая точка это зло :-)
"но сейчас, чтобы компенсировать растущую мощность компьютеров, программисты используют фреймворки"

igor

  • Sr. Member
  • ****
  • Сообщений: 438
    • Просмотр профиля
Re:Сравнение вещественных чисел
« Ответ #2 : Март 14, 2011, 03:07:41 pm »
Суть проблемы не только в различии представления, но и вообще в потере точности при вычислениях.
Да, потеря точности есть. И с этим фактом принципиально ничего не поделать. Увеличение разрядности уменьшит погрешность, но не решит проблему в корне. Подчёркиваю (уже повторно), что с этим я даже не предлагаю бороться.

Но как можно запретить сравнивать вещественные числа? Ведь необходимость в этом обычно исходит из самой задачи.

Я начинаю склоняться к мысли, что проблема сравнения вещественных чисел всё-таки решабельна.

igor

  • Sr. Member
  • ****
  • Сообщений: 438
    • Просмотр профиля
Re:Сравнение вещественных чисел
« Ответ #3 : Март 14, 2011, 03:13:09 pm »
Плавающая точка - это не зло, а объективная реальность, данная нам в стандарте IEEE Standard 754 и закреплённая в языке.  :)

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re:Сравнение вещественных чисел
« Ответ #4 : Март 14, 2011, 03:15:49 pm »
Но как можно запретить сравнивать вещественные числа? Ведь необходимость в этом обычно исходит из самой задачи.

Ну в смысле как? Как обычно: (x + погрешность) > y > (x - погрешность). Причем погрешность выбирается "из самой задачи".

igor

  • Sr. Member
  • ****
  • Сообщений: 438
    • Просмотр профиля
Re:Сравнение вещественных чисел
« Ответ #5 : Март 14, 2011, 03:25:44 pm »
Ну в смысле как? Как обычно: (x + погрешность) > y > (x - погрешность). Причем погрешность выбирается "из самой задачи".
Да, я сейчас так и поступаю (кстати, сравнение как таковое в этом варианте никуда не делось).

Но свои "хотелки" я уже озвучил: перенести решение с уровня задачи на уровень языка (чем и рассмешил Info21  :)).

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re:Сравнение вещественных чисел
« Ответ #6 : Март 14, 2011, 03:34:22 pm »
Ну в смысле как? Как обычно: (x + погрешность) > y > (x - погрешность). Причем погрешность выбирается "из самой задачи".
Да, я сейчас так и поступаю (кстати, сравнение как таковое в этом варианте никуда не делось).

Дык. Конечно речь о сравнении на равенство. Больше/меньше проблем не создает.

Но свои "хотелки" я уже озвучил: перенести решение с уровня задачи на уровень языка (чем и рассмешил Info21  :)).

Общего решения пока нет, переносить нечего :) А проблема есть. Для начала неплохо бы ее явно обозначить - например, запретив сравнение на равенство :) А чтоб не так жестко, предоставить какую-нибудь стандартную функцию: eq(x, y, eps).

igor

  • Sr. Member
  • ****
  • Сообщений: 438
    • Просмотр профиля
Re:Сравнение вещественных чисел
« Ответ #7 : Март 14, 2011, 03:48:55 pm »
Кроме того, что я просто не хочу запрещать сравнение вещ. чисел на равенство, я ещё и не представляю как это сделать безболезненно. Ведь вместо банальных x и y  в общем случае могут быть сложные выражения (либо x и y вычисляются перед использованием в логическом выражении), тип результата которых станет известен только на этапе выполнения программы. И что должна делать программа, если этот тип окажется вещественным? Аварийное завершение?

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re:Сравнение вещественных чисел
« Ответ #8 : Март 14, 2011, 03:52:55 pm »
Кроме того, что я просто не хочу запрещать сравнение вещ. чисел на равенство, я ещё и не представляю как это сделать безболезненно. Ведь вместо банальных x и y  в общем случае могут быть сложные выражения (либо x и y вычисляются перед использованием в логическом выражении), тип результата которых станет известен только на этапе выполнения программы. И что должна делать программа, если этот тип окажется вещественным? Аварийное завершение?

Гхм. Если речь идет о статически-типизированном языке (а-ля оберон), то тип всех выражений известен на этапе компиляции. Независимо от сложности. Так что "оказаться вещественным" он может только на этапе компиляции.

igor

  • Sr. Member
  • ****
  • Сообщений: 438
    • Просмотр профиля
Re:Сравнение вещественных чисел
« Ответ #9 : Март 14, 2011, 03:58:53 pm »
Аварийное завершение?
Если речь идет о статически-типизированном языке (а-ля оберон), то ...
Хорошо, тогда вопрос снимается.

А что Вы скажете по поводу идеи, которую я изложил здесь: http://forum.oberoncore.ru/viewtopic.php?f=29&t=3327&p=61464#p61464 (см. также предыдущий пост)

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re:Сравнение вещественных чисел
« Ответ #10 : Март 14, 2011, 04:26:40 pm »
А что Вы скажете по поводу идеи, которую я изложил здесь: http://forum.oberoncore.ru/viewtopic.php?f=29&t=3327&p=61464#p61464 (см. также предыдущий пост)

ИМХО, нельзя просто брать и чего-то отсекать. Вещественные числа - это сложно. Можно принять какие-то "умолчания" и попытаться сделать просто. Но не в языке, с претензией на максимальную прозрачность и отсутствие скрытых граблей. По моему опыту, стыковок между вещественными/целыми бывает не так уж и много и их хочется видеть в явном виде. И либо эти стыковки совсем не парят (показать на экране график функции, так что +/- пиксел не принципиален) и тогда нужно какое-нибудь дубовое (максимально быстрое) округление. Либо это принципиальная штука (разница в пиксел принципиальна, потому что она заметна в случае позиционирования фигур с "почти одинаковыми" координатами) и никакие встроенные в компилятор штуки не спасут - нужен индивидуальный подход.

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re:Сравнение вещественных чисел
« Ответ #11 : Март 14, 2011, 04:40:52 pm »
Примерно из той же оперы. Есть такой фрэймворк на маке (вроде и не только) - quartz. Грубо говоря, чтоб рисовать где только можно и как только можно. Там все круто - забудьте о пикселах, вот вам вещественные координаты, антиалиасинг и т.д. Классно. Только при ближайшем рассмотрении оказывается, что для того, чтобы нарисованное выглядело прилично на мониторе - нужно знать, что такое пиксел и формировать координаты соответственно. Например, горизонтальна линия с координатами (0,0) - (100,0) и толщиной 1 - выглядит неприемлимо. А вот с координатами (0,0.5) - (100,0.5) - нормально. А вот линия с толщиной 2 - наоборот. Приличное рисование геометрических примитивов в таком фрэймворке - страшный гемор и требует "особенного" подхода к округлению и преобразованиям между целыми и вещественными. В компилятор такую фигню не засунуть в принципе.

igor

  • Sr. Member
  • ****
  • Сообщений: 438
    • Просмотр профиля
Re:Сравнение вещественных чисел
« Ответ #12 : Март 14, 2011, 04:43:32 pm »
Цитата: vlad
ИМХО, нельзя просто брать и чего-то отсекать. Вещественные числа - это сложно. Можно принять какие-то "умолчания" и попытаться сделать просто. Но не в языке, с претензией на максимальную прозрачность и отсутствие скрытых граблей. По моему опыту, стыковок между вещественными/целыми бывает не так уж и много и их хочется видеть в явном виде. И либо эти стыковки совсем не парят (показать на экране график функции, так что +/- пиксел не принципиален) и тогда нужно какое-нибудь дубовое (максимально быстрое) округление. Либо это принципиальная штука (разница в пиксел принципиальна, потому что она заметна в случае позиционирования фигур с "почти одинаковыми" координатами) и никакие встроенные в компилятор штуки не спасут - нужен индивидуальный подход.
Спасибо, интересное мнение.
Но пока я всё-же остаюсь при своём мнении. Если абсолютная точность принципиально недостижима, то реализация неточного сравнения - это не "скрытые грабли", а разумный компромисс. Нужно только не забыть прописать об этом в спецификации!!!

PS: 0.1 # 0.1 -- вот это конкретные грабли.  :D

igor

  • Sr. Member
  • ****
  • Сообщений: 438
    • Просмотр профиля
Re:Сравнение вещественных чисел
« Ответ #13 : Март 14, 2011, 04:49:37 pm »
Есть такой фрэймворк на маке (вроде и не только) - quartz. ... Приличное рисование геометрических примитивов в таком фрэймворке - страшный гемор и требует "особенного" подхода к округлению и преобразованиям между целыми и вещественными.
Думаю, что дело здесь в откровенно плохой реализации (без учёта реального растра, на котором нужно рисовать). Скажем, в том же MS Visio таких проблем не возникает (там другие проблемы  :)).

vlad

  • Hero Member
  • *****
  • Сообщений: 1391
    • Просмотр профиля
Re:Сравнение вещественных чисел
« Ответ #14 : Март 14, 2011, 05:03:07 pm »
Есть такой фрэймворк на маке (вроде и не только) - quartz. ... Приличное рисование геометрических примитивов в таком фрэймворке - страшный гемор и требует "особенного" подхода к округлению и преобразованиям между целыми и вещественными.
Думаю, что дело здесь в откровенно плохой реализации (без учёта реального растра, на котором нужно рисовать).

Не, реализация там не причем. Там просто приняты другие "правила" рисования. Они по-своему хороши и с математической точки зрения намного естественнее и правильнее классических "пиксельных" правил. Причем это все хорошо работает, например, для принтеров, потому что масштабы не те. А на мониторах это нифига не работает и реализация не может "правильно учесть растр" - она не может знать в какую сторону ей сместить линию с координатой 0.5 (вверх или вниз), поэтому она рисует две полупрозрачные линии с координатами 0 и 1.