Re[5]: memcmp и float
От: Cyberax Марс  
Дата: 31.08.07 07:13
Оценка:
Здравствуйте, rg45, Вы писали:

R>Что, неужели (negative_x == x) ложно?

Вполне может оказаться, что так. Зависит от реализации синуса.
Sapienti sat!
Re[6]: memcmp и float
От: rg45 СССР  
Дата: 31.08.07 07:21
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Здравствуйте, rg45, Вы писали:


R>>Что, неужели (negative_x == x) ложно?

C>Вполне может оказаться, что так. Зависит от реализации синуса.
Согласен, зависит. Я синус сюда влепил, чтоб помешать компилятору соптимизировать весь этот фрагмент. По смысу вместо синуса нужно подставить функцию, которая возвращает "твердый ноль". У меня синус удовлетворяет этому требованию, я рискнул предположить, что у большинства присутствующих тоже.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
--
Не можешь достичь желаемого — пожелай достигнутого.
Re[3]: memcmp и float
От: AstroMan  
Дата: 01.09.07 09:39
Оценка:
Здравствуйте, McSeem2, Вы писали:

MS>И пожалуйста, имейте смелость высмеять от меня в лицо того университетского преподавателя, который скажет вам, что сравнивать плавающие числа на равенство нельзя. Такое высказывание можно простить в школе, на первом уроке информатики, но никак не в универе.


Можно сказать проще, что все стандартные эпсилоны относятся только к мантиссе числа. В большинстве задач надо вводить погрешность из проблемной области (например, 0.001 см для разметки текста на странице или 1.0E+30 г для массы звезд).
Re[3]: memcmp и float
От: Шахтер Интернет  
Дата: 02.09.07 01:49
Оценка:
Здравствуйте, McSeem2, Вы писали:

Сравнивать плавающие числа или не сравнивать и как именно -- зависит исключительно о решаемой задачи. Вне конкретного контекста обсуждать можно лишь свойства примитивных опрераций -- в данном случае операции сравнения.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[2]: memcmp и float
От: Шахтер Интернет  
Дата: 02.09.07 01:50
Оценка:
Здравствуйте, Cyberax, Вы писали:

C>Здравствуйте, Аноним, Вы писали:


А>>Насколько я помню, memcmp сравнивает блоки памяти побайтно. Размер переменной типа float составляет 4 байта. Уместно ли использование memcmp для сравнения массивов типа float? Поэлементное сравнение массивов слишком уж медленное для моей ситуации. Если memcmp не подходит, кто как решал проблему производительности при сравнении массивов чисел с плавающей запятой?

C>Про сравнение на равенство тебе уже тут написали

C>Однако, нормализованые плавающие числа без всяких там NAN'ов и прочих исключительных значений МОЖНО корректно сравнивать, используя простое побайтное сравнение. Его результат будет гарантировано правильным.


+0 -0
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[3]: memcmp и float
От: Шахтер Интернет  
Дата: 02.09.07 01:53
Оценка:
Здравствуйте, rg45, Вы писали:

R>Если битовое представление a и b не одинаково, то эти два числа не равны и выражение a == b ложно.


Это не так. Есть +0 и -0, есть так же ненормализованные числа.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[4]: memcmp и float
От: McSeem2 США http://www.antigrain.com
Дата: 02.09.07 20:58
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>Сравнивать плавающие числа или не сравнивать и как именно -- зависит исключительно о решаемой задачи. Вне конкретного контекста обсуждать можно лишь свойства примитивных опрераций -- в данном случае операции сравнения.


Безусловно. Но надо иметь хотя бы начальную печку, от которой танцевать. А то так и будут писать ахинею типа if(fabs(a-b) <= DBL_EPSILON)...
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[4]: memcmp и float
От: McSeem2 США http://www.antigrain.com
Дата: 02.09.07 21:01
Оценка:
Здравствуйте, AstroMan, Вы писали:

AM>Можно сказать проще, что все стандартные эпсилоны относятся только к мантиссе числа. В большинстве задач надо вводить погрешность из проблемной области (например, 0.001 см для разметки текста на странице или 1.0E+30 г для массы звезд).


Я специально написал такой развернутый ответ, за еще и "с эмоциями". Сказать проще конечно можно, но это увы не наглядно и часто не доходит.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[3]: memcmp и float
От: Cyberax Марс  
Дата: 02.09.07 21:15
Оценка:
Здравствуйте, Шахтер, Вы писали:

C>>Однако, нормализованые плавающие числа без всяких там NAN'ов и прочих исключительных значений МОЖНО корректно сравнивать, используя простое побайтное сравнение. Его результат будет гарантировано правильным.

Ш>+0 -0
-0 < +0, AFAIR. А что ты хотел?
Sapienti sat!
Re[3]: memcmp и float
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 16.12.07 07:58
Оценка:
Здравствуйте, McSeem2, Вы писали:

MS>И пожалуйста, имейте смелость высмеять от меня в лицо того университетского преподавателя, который скажет вам, что сравнивать плавающие числа на равенство нельзя. Такое высказывание можно простить в школе, на первом уроке информатики, но никак не в универе.


Я всё-таки на это возражу:)) Дело в том, что в вычислительном алгоритме ситуаций, которые достаточно просто сводятся к

  double b = a;
  if (a != b) { шеф, усё пропало! }


крайне мало — я бы сказал, что их вообще не бывает.

А вот ситуаций, когда пишут код вида

  for(double x = 0.0; x <= 20.0; x += 0.1) {
    ...
  }


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

Именно поэтому устанавливать принцип "не сравнивайте на точное равенство! всегда сравнивайте величину разницы" вместе с некоторыми простыми советами типа "замените x<=20.0 на x<=20.5" имеет право на жизнь и тем более в университете. А ещё есть конверсии, когда double где-то был перенесен во float, а потом обратно... Найти случаи, когда надо сравнивать более просто, грамотный программист сможет — а если не сможет, ему вообще в вычислительной математике делать нечего. А вот сделать, чтобы правильное сравнение вошло "в плоть и кровь" — преподаватель таки должен.

По поводу вот этого:

MS> Конечно же, есть случаи, когда диапазон чисел более-менее известен и предсказуем. Скажем, 0...1000. В этом случае, для сравнения на приблизительное равенство можно взять константу, типа 1000*16*DBL_EPSILON. Но надо иметь в виду, что такое сравнение фактически превращает всю идею плавающей точки в фиксированную точку (догадайтесь, почему).


До определённой степени та же "фиксированная точка" тут совсем неплоха. По крайней мере при сравнении. Только, наверно, не при 0...1000, а хотя бы при 10...1000. Общих рецептов всё равно не будет, в вычислительной математике огромное количество тонкостей, зависящих и от специфики исходной задачи... я когда-то наигрался с этим.
The God is real, unless declared integer.
Re[5]: memcmp и float
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 16.12.07 07:59
Оценка:
Здравствуйте, McSeem2, Вы писали:

MS>Здравствуйте, Шахтер, Вы писали:


Ш>>Сравнивать плавающие числа или не сравнивать и как именно -- зависит исключительно о решаемой задачи. Вне конкретного контекста обсуждать можно лишь свойства примитивных опрераций -- в данном случае операции сравнения.


MS>Безусловно. Но надо иметь хотя бы начальную печку, от которой танцевать. А то так и будут писать ахинею типа if(fabs(a-b) <= DBL_EPSILON)...


Вот с этим полностью согласен. (Пишу это явно на всякий случай)
The God is real, unless declared integer.
Re[4]: memcmp и float
От: McSeem2 США http://www.antigrain.com
Дата: 17.12.07 16:50
Оценка: 16 (3) +2
Здравствуйте, netch80, Вы писали:

N>Я всё-таки на это возражу Дело в том, что в вычислительном алгоритме ситуаций, которые достаточно просто сводятся к


N>
N>  double b = a;
N>  if (a != b) { шеф, усё пропало! }
N>


N>крайне мало — я бы сказал, что их вообще не бывает.


Бывает и довольно много, по крайней мере в моей практике. Например, восстановить связность графа по набору ребер и координатам их концов. Вполне практическая задача, необходимая для растеризации данных из Flash. Вообще, в вычислительной геометрии встречается сплошь и рядом.

N>А вот ситуаций, когда пишут код вида


N>
N>  for(double x = 0.0; x <= 20.0; x += 0.1) {
N>    ...
N>  }
N>


N>много — фактически, каждому хотя бы раз приходилось писать такое (и потом удивляться результату — а куда делась последняя итерация?)


Это несколько другой эффект, связанный с невозможностью точного представления десятичных дробей в двоичном виде. Числа 0.1 в двоичном виде не существует. Вышеуказанный цикл может сработать неправильно даже с фиксированной точкой. Здесь главным условием является наличие десятичной дроби (причем, не всякой), представленной в двоичном виде. Например, при обработке в BCD все сработает нормально. В случае с таким циклом надо именно что разъяснить студентам этот побочный эффект на как можно более ранних стадиях. Например:

  for(double x = 0.0; x <= 20.0; x += 0.1) {  // неправильно
    ...
  }

  for(double x = 0.0; x <= 200.0; x += 1.0) {  // правильно
    ...
  }

  for(double x = 0.0; x <= 100.0; x += 0.5) {  // правильно
    ...
  }


Другими словами, требуется обеспечить понимание, что некоторые десятичные дроби не имеют точного представления в двоичном виде.

Так называемые практические советы, типа "x <= 20.05" опасны, поскольку могут только запутать и сбить с толку. И главное — они лечат симптом, а не болезнь, еще больше отдаляя понимание сущности. Вот после того, как наступило понимание, можно дать подобный совет, но не раньше. Но при этом и надобность в подобном совете отпадает — человек уже понимает сущность и сам сообразит что к чему.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[4]: memcmp и float
От: McSeem2 США http://www.antigrain.com
Дата: 17.12.07 17:26
Оценка:
Здравствуйте, Шахтер, Вы писали:

Ш>Это не так. Есть +0 и -0, есть так же ненормализованные числа.


Раз уж подняли тему, то что это за зверь такой, ненормализованные числа? Ведь при нормальных условиях, float и double всегда нормализованы. Они просто не могут быть ненормализованными, поскольку старший разряд мантиссы не хранится, а только лишь подразумевается, поскольку он всегда равен 1. Ненормализованными являются только числа с минимально возможным значением порядка, для float — меньше 1.2e-38. Но это уже такой экстрим, до которого лучше не доводить. И AFAIK, не все архитектуры правильно понимают ненормализованные числа — можно нарваться на несовместимость при передаче данных.

Исключительной ситуацией при нормальных условиях является только +0, -0, если всякие inf, NaN рссмативать как ошибочные ситуации. Но и +0, -0 — это явление того же порядка, что и сравнение в доверительном интервале — если числа получены одинаковым способом, их битовые значения должны быть строго равны. С этой точки зрения, при определенных ограничениях побитовое сравнение сработает точно так же, как и сравнение на равенство и, следовательно, вполне уместно. Необходимо только четко понимать эти ограничения.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[5]: memcmp и float
От: netch80 Украина http://netch80.dreamwidth.org/
Дата: 17.12.07 17:48
Оценка:
Здравствуйте, McSeem2, Вы писали:

MS>Здравствуйте, Шахтер, Вы писали:


Ш>>Это не так. Есть +0 и -0, есть так же ненормализованные числа.


MS>Раз уж подняли тему, то что это за зверь такой, ненормализованные числа? Ведь при нормальных условиях, float и double всегда нормализованы. Они просто не могут быть ненормализованными, поскольку старший разряд мантиссы не хранится, а только лишь подразумевается, поскольку он всегда равен 1.


В форматах IEEE754 — да. Но если Вы думаете, что ими ограничивается мир, то ошибаетесь.:)
Даже в x87 во внутреннем 80-битном представлении старший разряд мантиссы хранится явно и может быть 0. А на других платформах — тем более. На S/360 вообще были разные команды для вычислений с нормализацией результата и без оной.
The God is real, unless declared integer.
Re[2]: memcmp и float
От: McSeem2 США http://www.antigrain.com
Дата: 18.12.07 15:17
Оценка:
Здравствуйте, MasterZiv, Вы писали:

MZ>Я считаю, что нет. На некоторых платформах число с плавающей точкой

MZ>может быть ненормализировано, и при этом два одинаковых по значению
MZ>числа будут иметь разные байтовые представления. И при сравнении
MZ>побайтно они будут разные, а фактически одинаковые.

Если речь идет о float/double в формате IEEE754, то числа там всегда нормализованные, за исключением клинических случаев, типа 1e-40 для 32-битового float.

MZ>Например, числа 1*10**2 , 100 и 0.1*10**3 одинаковые, но имеют

MZ>разное представление. Так же может быть и с двоично кодированными float.

Не может. Дело в том, что во float в принципе невозможно представить ненормализованное число. Это обусловлено экономией одного бита. В нормализованном числе (в двоичном представлении, конечно же) старший бит мантиссы всегда равен единице. Следовательно, его можно не хранить, а только подразумевать. Например, двоичное представление 0.00101 будет воспринято как нормализованное 0.100101. В конце концов, возьмите число 1.0 и посмотрите, чему равна его мантисса — она равна нулю.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[3]: memcmp и float
От: Аноним  
Дата: 19.03.08 03:39
Оценка:
Из всего здесь сказанного я понял что стратегия сравнения ЧСПТ зависит от проблемы над которой идет работа.
Но вот простое сравнене синуса 90.0 и косинуса 0.0 без привязки к конкретной проблемной области не получается (VS2003):

sin(90.0) = 0.999999999999999
cos(0.0) = 1
abs(cos(0.0) — sin(90.0)) = 9.992007221626409e-016
>
std::numeric_limits<double>::epsilon() = 2.220446049250313e-016
Re[3]: memcmp и float
От: Vamp Россия  
Дата: 19.03.08 07:43
Оценка:
Ш>Незачет. Сравнение плавающих чисел всегда даёт правильный результат.
Вообще-то мне в жизни не доводилось встречать плавающих чисел. БДывали плавающие рыбы, плавающие животные, даже плавающие птицы бывают... А чисел не видал.
Да здравствует мыло душистое и веревка пушистая.
Re[5]: memcmp и float
От: s_viy  
Дата: 20.03.08 08:43
Оценка:
Здравствуйте, Аноним, Вы писали:

А>Здравствуйте, qvasic, Вы писали:


А>>>То есть нет более быстрого способа сравнения длинных массивов чисел с плавающей запятой как поэлементное сравнение?


Q>>остается только магия


А>вставка на ассемблере может дать заметный прирост производительности?

А>З.Ы. Опыта с ассемблером, к сожалению, нет, поэтому и задаю такой вопрос

Опыта тоже нет, но работал с проектом где для перебора и сравнения элементов использовался ассемблер, что давало существенный прирост производительности. Однако это имеет смысл только при использовании каких-то специальных инструкций процессора, о которых компилятор не знает. А в общем случае он сгенерит код не хуже чем ты сам напишешь.
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.