Зачем мне использовать дополнение 2 для сравнения двух двойников вместо сравнения их различий со значением epsilon?

StackOverflow https://stackoverflow.com/questions/96233

  •  01-07-2019
  •  | 
  •  

Вопрос

Упомянутый здесь и здесь... Почему я должен использовать дополнение two вместо метода epsilon?Похоже, что метод epsilon был бы достаточно хорош для большинства случаев.


Обновить: Я чисто ищу теоретическую причину, по которой вы бы использовали одно вместо другого.Я всегда использовал метод эпсилона.

Кто-нибудь успешно использовал сравнение дополнений 2?Почему?Почему бы и нет?

Это было полезно?

Решение

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

http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm

но если вы не настраиваете производительность, я бы предпочел epsilon, чтобы люди могли отлаживать ваш код

Другие советы

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

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

Например:

Что такое хороший эпсилон при сравнении расстояния в милях между Атлантой, штат Джорджия, Далласом, Техас, и каким-либо местом в Огайо?

Что такое хороший эпсилон при сравнении расстояния в милях между моей левой ногой, моей правой ногой и компьютером под моим столом?

Редактировать:

Хорошо, я получаю довольно много людей, которые не понимают, почему вы не знаете, что такое ваш эпсилон.

Еще в старые времена lore я написал две программы, которые работали с NeverWinter Nights (игрой от BioWare).Одна из программ взяла двоичную модель и преобразовала ее в ASCII.Другая программа взяла ASCII-модель и скомпилировала ее в двоичный файл.Один из тестов, которые я написал, состоял в том, чтобы взять все двоичные модели BioWare, декомпилировать их в ASCII, а затем обратно в двоичный код.Затем я сравнил свою двоичную версию с оригинальной от BioWare.Одной из проблем во время сравнения была проблема с некоторыми незначительными отклонениями в значениях с плавающей запятой.Поэтому вместо того, чтобы придумывать кучу разных ЭПСИЛОНОВ для каждого типа чисел с плавающей запятой (вершинные, нормальные и т.д.), я хотел использовать что-то вроде этого сравнения двух комплиментов.Таким образом, можно избежать всей проблемы с множественным ЭПСИЛОНОМ.

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

Редактировать:

ЛОЛ, за это проголосовали разные люди "за" и "против".

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

Как вы можете сравнить 1e23 и 1.0001e23 с эпсилоном и при этом сравнить 1e-23 и 5.2e-23, используя тот же эпсилон?Конечно, вы можете выполнять некоторые динамические эпсилон-трюки, но в этом весь смысл целочисленного сравнения (которое НЕ требует точности целых чисел).

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

Редактировать

Стив, давай посмотрим на то, что ты сказал в комментариях:

- Но ты же знаешь, что для тебя значит равенство...Следовательно, вы должны быть в состоянии найти подходящий эпсилон".

Переверните это утверждение , чтобы сказать:

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

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

Когда дело доходит до скорости, следуйте этим правилам:

  1. Если вы не очень опытный разработчик, не проводите оптимизацию.
  2. Если вы опытный разработчик, пока не проводите оптимизацию.

Сделайте это самым простым способом.

Алекс

Оскар прав.Не связывайтесь с этим, если только вам действительно не нужна такая производительность.

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

Использование любого метода, который сравнивает побитово, приведет к проблемам, когда дроби будут представлены приближенно.Все числа с плавающей запятой с дробями, которые не выражены в степенях двойки (1/2, 1/4, 1/8, 1/65536, & c) являются аппроксимированными.Так же, конечно, обстоят дела со всеми иррациональными числами.

плавающая треть = 1/3;число с плавающей запятой два= 2,0;плавающий another_two=третий*6.0;if(two != another_two) вывести ("Приближение! ");

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top