memcmp и float
От: Аноним  
Дата: 29.08.07 18:16
Оценка:
Насколько я помню, memcmp сравнивает блоки памяти побайтно. Размер переменной типа float составляет 4 байта. Уместно ли использование memcmp для сравнения массивов типа float? Поэлементное сравнение массивов слишком уж медленное для моей ситуации. Если memcmp не подходит, кто как решал проблему производительности при сравнении массивов чисел с плавающей запятой?
Re: memcmp и float
От: gandjustas Россия http://blog.gandjustas.ru/
Дата: 29.08.07 18:46
Оценка:
Здравствуйте, Аноним, Вы писали:


А>Уместно ли использование memcmp для сравнения массивов типа float?


Нет. Вообще прямое сравнение чисел с плавающией запятой, вида (a==b) может дать неправильный результат
Re: memcmp и float
От: bkat  
Дата: 29.08.07 18:56
Оценка:
Здравствуйте, Аноним, Вы писали:


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


memcmp конечно же не подходит. Все еще сложнее.
Даже поэлементное сравнение в стиле a==b в большинстве случаев не подходят.
Сравнивать надо с некой погрешностью.
Re[2]: memcmp и float
От: Аноним  
Дата: 29.08.07 19:02
Оценка:
Здравствуйте, gandjustas, Вы писали:

G>Нет. Вообще прямое сравнение чисел с плавающией запятой, вида (a==b) может дать неправильный результат


По поводу сравнения чисел методом (a == b) согласен, вместо этого для float следует пользоваться ( fabs(a — b) < 0.0000001 )

То есть нет более быстрого способа сравнения длинных массивов чисел с плавающей запятой как поэлементное сравнение?
Re[3]: memcmp и float
От: qvasic Украина  
Дата: 29.08.07 19:27
Оценка:
А>То есть нет более быстрого способа сравнения длинных массивов чисел с плавающей запятой как поэлементное сравнение?

остается только магия
Re[4]: memcmp и float
От: Аноним  
Дата: 29.08.07 19:34
Оценка:
Здравствуйте, qvasic, Вы писали:

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


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


вставка на ассемблере может дать заметный прирост производительности?
З.Ы. Опыта с ассемблером, к сожалению, нет, поэтому и задаю такой вопрос
Re[3]: memcmp и float
От: Uzumaki Naruto Ниоткуда  
Дата: 29.08.07 19:42
Оценка:
Не 0.0000001, а EPS — это значение определено в CRT =)

http://files.rsdn.org/67166/naruto.png
Re[4]: memcmp и float
От: Аноним  
Дата: 29.08.07 19:48
Оценка: 1 (1) +3
Здравствуйте, Uzumaki Naruto, Вы писали:

UN>Не 0.0000001, а EPS — это значение определено в CRT =)


Не EPS, а то, что тебе надо в зависимости от задачи...
Re: memcmp и float
От: Шахтер Интернет  
Дата: 29.08.07 22:38
Оценка:
Здравствуйте, Аноним, Вы писали:


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


Неуместно.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[2]: memcmp и float
От: Шахтер Интернет  
Дата: 29.08.07 22:39
Оценка: 2 (2) +1 :)))
Здравствуйте, gandjustas, Вы писали:

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



А>>Уместно ли использование memcmp для сравнения массивов типа float?


G>Нет. Вообще прямое сравнение чисел с плавающией запятой, вида (a==b) может дать неправильный результат


Незачет. Сравнение плавающих чисел всегда даёт правильный результат.
В XXI век с CCore.
Копай Нео, копай -- летать научишься. © Matrix. Парадоксы
Re[2]: memcmp и float
От: rg45 СССР  
Дата: 30.08.07 06:28
Оценка: +1
Здравствуйте, gandjustas, Вы писали:

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



А>>Уместно ли использование memcmp для сравнения массивов типа float?


G>Нет. Вообще прямое сравнение чисел с плавающией запятой, вида (a==b) может дать неправильный результат


Если битовое представление a и b одинаково, то эти два числа равны и выражение a == b истинно. Если битовое представление a и b не одинаково, то эти два числа не равны и выражение a == b ложно. Исключение составляют лишь QNAN'ы, для которых по задумке число не равно само себе. Где же неправильный результат?

З.Ы. Часто случается, что при операциях с числами с плавающей точкой мы получаем результат с некоторой погрешностью и часто при сравнении эту погрешность нужно учитывать. Но сравнение дает правильный результат все-таки.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
--
Завтра сегодня будет вчера
Re: memcmp и float
От: Erop Россия  
Дата: 30.08.07 06:53
Оценка:
Здравствуйте, Аноним, Вы писали:

А>кто как решал проблему производительности при сравнении массивов чисел с плавающей запятой?


Поясни зачем такое надо?
Может быть, например, тебе надо сравнить много-много векторов между собой? И почти все они различны?
Тогда тебе поможет такой трюк.
1) Округдляешь всё на целочисленную сетку (ну типа с фиксированной точкой)
2) Это сравниваешь быстро
3) Потом среди тех кто "примерно равен" ищешь "равных точно"
Все эмоциональные формулировки не соотвествуют действительному положению вещей и приведены мной исключительно "ради красного словца". За корректными формулировками и неискажённым изложением идей, следует обращаться к их автором или воспользоваться поиском
Re[3]: memcmp и float
От: alzt  
Дата: 30.08.07 07:39
Оценка:
Здравствуйте, rg45, Вы писали:

G>>Нет. Вообще прямое сравнение чисел с плавающией запятой, вида (a==b) может дать неправильный результат


R>Если битовое представление a и b одинаково, то эти два числа равны и выражение a == b истинно. Если битовое представление a и b не одинаково, то эти два числа не равны и выражение a == b ложно. Исключение составляют лишь QNAN'ы, для которых по задумке число не равно само себе. Где же неправильный результат?


R>З.Ы. Часто случается, что при операциях с числами с плавающей точкой мы получаем результат с некоторой погрешностью и часто при сравнении эту погрешность нужно учитывать. Но сравнение дает правильный результат все-таки.


Результат правильный с точке зрения эквивалентности двоичного представления, но может быть не правильным с точки зрения логики программы, как раз из-за округлений.
Re[4]: memcmp и float
От: rg45 СССР  
Дата: 30.08.07 08:03
Оценка: 4 (1)
Здравствуйте, alzt, Вы писали:

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


G>>>Нет. Вообще прямое сравнение чисел с плавающией запятой, вида (a==b) может дать неправильный результат


R>>Если битовое представление a и b одинаково, то эти два числа равны и выражение a == b истинно. Если битовое представление a и b не одинаково, то эти два числа не равны и выражение a == b ложно. Исключение составляют лишь QNAN'ы, для которых по задумке число не равно само себе. Где же неправильный результат?


R>>З.Ы. Часто случается, что при операциях с числами с плавающей точкой мы получаем результат с некоторой погрешностью и часто при сравнении эту погрешность нужно учитывать. Но сравнение дает правильный результат все-таки.


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


А можем ли мы в этом случае говорить, что операция сравнения дает неправильный результат? ИМХО, в этом случае правильнее говорить, что логика программы содержит ошибку, поскольку не учитывает погрешность, возможную при операциях с числами с плавающей точкой.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
--
Завтра сегодня будет вчера
Re: memcmp и float
От: MasterZiv СССР  
Дата: 30.08.07 09:02
Оценка: 2 (1) +1
Аноним 365 пишет:
> Насколько я помню, memcmp сравнивает блоки памяти побайтно. Размер
> переменной типа float составляет 4 байта. Уместно ли использование
> memcmp для сравнения массивов типа float? Поэлементное сравнение
> массивов слишком уж медленное для моей ситуации. Если memcmp не
> подходит, кто как решал проблему производительности при сравнении
> массивов чисел с плавающей запятой?

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

Например, числа 1*10**2 , 100 и 0.1*10**3 одинаковые, но имеют
разное представление. Так же может быть и с двоично кодированными float.
Posted via RSDN NNTP Server 2.1 beta
Re[3]: memcmp и float
От: Аноним  
Дата: 31.08.07 03:11
Оценка: +1
R>Если битовое представление a и b одинаково, то эти два числа равны и выражение a == b истинно. Если битовое представление a и b не одинаково, то эти два числа не равны и выражение a == b ложно. Исключение составляют лишь QNAN'ы, для которых по задумке число не равно само себе. Где же неправильный результат?

-0.0 == 0.0
Про сравнение double
От: McSeem2 США http://www.antigrain.com
Дата: 31.08.07 04:59
Оценка: 347 (43) +2
#Имя: FAQ.cpp.double==double
Здравствуйте, gandjustas, Вы писали:

G>Нет. Вообще прямое сравнение чисел с плавающией запятой, вида (a==b) может дать неправильный результат

UN>Не 0.0000001, а EPS — это значение определено в CRT =)

. . .ну и т.д.

Так. Тут начался беспредел с ужасами про сравнение плавающей точки на равенство. Требуется ликбез. Сравнивать плавающие числа (для педантов — значения переменных типа float или double) вполне можно и даже нужно. Но надо понимать сущность этой плавающей точки. А сущность заключается в том, что числа с фиксированной точкой (целые — это частный случай чисел с фиксированной точкой) имеют абсолютное значение погрешности, в отличие от чисел с плавающей точкой, где значение погрешности находится в прямой пропорциональности от модуля числа. Во всяком случае:
double a=3.1415;
double b=a;
if(a == b)
{
   . . .
}

Вот если этот if не сработает, то это означает, что компьютер сломался, а процессор издох.

Другое дело, когда числа вычислены разными способами — одно через синус, а другое — через экспоненту. Здесь действительно проверка на равенство скорее всего не сработает. Так же, как и не сработает сравнение с константой. Но это же относится и к целым числам, если скажем, мы нормализуем значения от 0...1 к 0...1000000000. То есть, не имеет значения, плавающие это числа или целые. В определенных ситуациях сравнивать их на строгое равенство нельзя. В этих ситуациях надо использовать некую Epsilon. И вот здесь-то и вылезает наружу вся безграмотность. Что такое DBL_EPSILON? — а это вот что. Это минимальное значение, которое при прибавлении его к единице, меняет значение этой единицы. Понимаете? — к единице! Строгой единице, числу 1.0 и ни к какому другому. Поэтому сравнивать числа с плавающей точкой на +/- DBL_EPSILON совершенно бессмысленно. Это сравнение выдает всю глубину невежества и неспособности думать мозгом. Факты таковы — плавающие числа больше 2.0 эту DBL_EPSILON просто не ощущают. Им что прибавляй ее, что что нет — ничего не меняет. Для этих чисел DBL_EPSILON является строгим нулем и просто не существует. В то же время, DBL_EPSILON имеет значение порядка 1e-16. Что это значит? А это значит, что числа в диапазоне Планковских масштабов (типа 1e-34) с точки зрения этой DBL_EPSILON будут все равны. То есть, эта 1e-16 становится слоном в посудной лавке. А ведь постоянная Планка ничуть не хуже скорости света — для этого собственно и были придуманы числа с плавающей точкой, чтобы отображать большие диапазоны значений с неким фиксированным количеством знаков.

Так для чего же все-таки нужна эта самая DBL_EPSILON (ну или FLT_EPSILON)? Нужна-ли? — нужна! Есть ситуации, когда действительно надо сравнивать числа в неком допустимом интервале. В каком? — А вот это как раз и зависит от абсолютного значения чисел и сущности вычислений. Короче говоря, надо эту Epsilon умножить на значение числа. А поскольку у нас два числа, то все усложняется — какое из них брать. То есть, корректное сравнение выглядит так:
if (fabs(a-b) <= DBL_EPSILON * fmax(fabs(a),fabs(b)))
{
  . . .Числа равны с относительной точностью DBL_EPSILON
}

Дорого? Да, дорого, а все остальное неправильно, такие дела. Но и это тоже неправильно! Дело в том, что этот DBL_EPSILON определяет разницу в 1 (один!) значащий бит экспоненты в приложении к числу 1.0. На практике такой разницы не встречается — числа либо строго равны, либо могут различаться больше чем на один значащий бит. Поэтому надо брать что-то типа 16*DBL_EPSILON, чтобы игнрорировать разницу в 4 младших бита (или примерно полторы последние значащие десятичные цифры из примерно 16 имеющихся).

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

Я вообще поражен уровню невежества — даже в весьма грамотной библиотеке GPC by Alan Murta используется тупое сравнение с константной Epsilon. На диапазонах экранных координат это все равно, что сравнение на строгое равенство, а на 1e-20 алгоритм вообще перестает работать.

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

Вроде бы все сказал. Дополняйте.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re[4]: memcmp и float
От: McSeem2 США http://www.antigrain.com
Дата: 31.08.07 05:10
Оценка: :)
Здравствуйте, Uzumaki Naruto, Вы писали:

UN>Не 0.0000001, а EPS — это значение определено в CRT =)


Срочно в школу! Изучать основы компьютерной грамотности.
McSeem
Я жертва цепи несчастных случайностей. Как и все мы.
Re: memcmp и float
От: Cyberax Марс  
Дата: 31.08.07 05:29
Оценка:
Здравствуйте, Аноним, Вы писали:

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

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

Однако, нормализованые плавающие числа без всяких там NAN'ов и прочих исключительных значений МОЖНО корректно сравнивать, используя простое побайтное сравнение. Его результат будет гарантировано правильным.
Sapienti sat!
Re[4]: memcmp и float
От: rg45 СССР  
Дата: 31.08.07 07:11
Оценка:
Здравствуйте, <Аноним>, Вы писали:

R>>Если битовое представление a и b одинаково, то эти два числа равны и выражение a == b истинно. Если битовое представление a и b не одинаково, то эти два числа не равны и выражение a == b ложно. Исключение составляют лишь QNAN'ы, для которых по задумке число не равно само себе. Где же неправильный результат?


А>-0.0 == 0.0

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

#include<iostream>
#include<cmath>

int main() 
{
  double x = std::sin(0.0);
  double negative_x = -x;
  std::cout << (negative_x == x) << std::endl;
}


Что, неужели (negative_x == x) ложно?
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
--
Завтра сегодня будет вчера
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.