Модераторы: LSD, AntonSaburov
  

Поиск:

Ответ в темуСоздание новой темы Создание опроса
> разница между 2-мя double 
V
    Опции темы
Pawl
Дата 12.11.2013, 08:55 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 649
Регистрация: 22.4.2008
Где: Витебск

Репутация: 7
Всего: 28



Отнимаю от одного double value другое. Затем определяю, результат получился большим, меньшим или равным 0. Проблема в том, что при вычитании одинаковых double-чисел получается не всегда 0, а +0.0000... или -0.0000.... Пока выкрутился так, что сравниваю результат вычитания не с 0, а с некой погрешностью:
Код

if (result >= 0.000001) {
    ...
} else if (result <= -0.000001) {
    ...
} else {
    ....
}

Но сдается мне, это костыль. Может, кто поделится лучшим способом?
Спасибо!


--------------------
В действительности всё совсем не так, как на самом деле
PM MAIL   Вверх
danilych
Дата 12.11.2013, 08:59 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Шустрый
*


Профиль
Группа: Участник
Сообщений: 72
Регистрация: 2.2.2011

Репутация: 3
Всего: 3



тип double не стоит использовать для точных вычислений - используйте BigDecimal
PM MAIL   Вверх
baldina
Дата 12.11.2013, 09:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 1
Всего: 101



гм. а чем плох double?

Добавлено через 7 минут и 29 секунд
уточню: что вы понимаете под точными вычислениями? и нужно ли ТС именно это, учитывая оверхед BigDecimal...
PM MAIL   Вверх
Pawl
Дата 12.11.2013, 10:08 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 649
Регистрация: 22.4.2008
Где: Витебск

Репутация: 7
Всего: 28



Цитата(danilych @  12.11.2013,  08:59 Найти цитируемый пост)
тип double не стоит использовать для точных вычислений - используйте BigDecimal

К сожалению, код не мой. Надо пользоваться тем, что есть.
Цитата(baldina @  12.11.2013,  09:48 Найти цитируемый пост)
 что вы понимаете под точными вычислениями? 

Поясню. Вот, я задал погрешность 0.000001, а разность получилась, к примеру, 0.0000001, т. е. не 0, а мой код это примет за 0. Конкретно для моего ТЗ Точные вычисления не суть важны, моего костыля хватит. Мне интересно, решаема ли данная проблема с double в принципе, или в подобных случаях корректно использовать только BigDecimal?


--------------------
В действительности всё совсем не так, как на самом деле
PM MAIL   Вверх
baldina
Дата 12.11.2013, 10:38 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 1
Всего: 101



Цитата(Pawl @  12.11.2013,  10:08 Найти цитируемый пост)
решаема ли данная проблема с double в принципе

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

double epsilon = 0.000001;
if (Math.abs (result) < epsilon) {
 // result == 0
}
else {
 // result != 0
}
...
if (Math.abs (result0-result1) < epsilon) {
  // result0 == result1
} else if (result0 > result1) {
} else {
 // result1 > result0
}

можно написать функции сравнения. это не костыль, это следствие представления double в компьютере

Добавлено через 8 минут и 12 секунд
Pawl, если расчеты финансовые, то BigDecimal удобнее, т.к. автоматически производит округление по одному из правил (в т.ч. банковское). А производительность вычислений в бухгалтерских расчетах обычно не является критичным параметром.
PM MAIL   Вверх
Pawl
Дата 12.11.2013, 12:50 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 649
Регистрация: 22.4.2008
Где: Витебск

Репутация: 7
Всего: 28



Цитата(baldina @  12.11.2013,  10:38 Найти цитируемый пост)
в принципе все примерно так, как вы и делаете

ОК, учту на будущее. Всем спасибо.


--------------------
В действительности всё совсем не так, как на самом деле
PM MAIL   Вверх
Mirkes
Дата 12.11.2013, 22:19 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 7
Всего: 17



Вообще говоря поймать +-0 в double можно, нашел этот прием а коде Arrays.
Код

        final long NEG_ZERO_BITS = Double.doubleToLongBits(-0.0d);
        /*
             * The sort is done in three phases to avoid the expense of using
             * NaN and -0.0 aware comparisons during the main sort.
             */

        /*
             * Preprocessing phase:  Move any NaN's to end of array, count the
             * number of -0.0's, and turn them into 0.0's.
             */
        int numNegZeros = 0;
        int i = 0, n = a.length;
        while (i < n) {
            if (a[i] != a[i]) {
                double swap = a[i];
                a[i] = a[--n];
                a[n] = swap;
                int sw = index[i];
                index[i] = index[n];
                index[n] = sw;
            } else {
                if (a[i] == 0 && Double.doubleToLongBits(a[i]) == NEG_ZERO_BITS) {
                    a[i] = 0.0d;
                    numNegZeros++;
                }
                i++;
            }



Правда судя по тексту и +0 и -0 таки равны просто 0. Нужно будет проверить.

Это сообщение отредактировал(а) Mirkes - 12.11.2013, 23:57


--------------------
Mirkes
PM MAIL   Вверх
Pawl
Дата 12.11.2013, 22:51 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 649
Регистрация: 22.4.2008
Где: Витебск

Репутация: 7
Всего: 28



Цитата(Mirkes @  12.11.2013,  22:19 Найти цитируемый пост)
Вообще говоря поймать +-0 в double можно

проблема в том, что иногда double - такой же double дает не +-0, а, к примеру, -5.551115123125783E-17. В таком случае ваш пример не поможет...
При выводе на экран, от "страшных" чисел и ненужных минусов я нашел способ избавиться при помощи методов класса java.text.NumberFormat.

Это сообщение отредактировал(а) Pawl - 12.11.2013, 22:57


--------------------
В действительности всё совсем не так, как на самом деле
PM MAIL   Вверх
baldina
Дата 13.11.2013, 10:54 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 3433
Регистрация: 5.12.2007
Где: Москва

Репутация: 1
Всего: 101



Цитата(Mirkes @  12.11.2013,  22:19 Найти цитируемый пост)
судя по тексту и +0 и -0 таки равны просто 0

просто 0 это +0
между собой они равны (в смысле результат сравнения true), хотя двоичное представление разное
PM MAIL   Вверх
Mirkes
Дата 13.11.2013, 12:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 586
Регистрация: 18.8.2011
Где: Красноярск

Репутация: 7
Всего: 17



Цитата(Pawl @  12.11.2013,  22:51 Найти цитируемый пост)
проблема в том, что иногда double - такой же double дает не +-0, а, к примеру, -5.551115123125783E-17. В таком случае ваш пример не поможет...
При выводе на экран, от "страшных" чисел и ненужных минусов я нашел способ избавиться при помощи методов класса java.text.NumberFormat.

А вот это уже говорит о том, что это не совсем одинаковые double  smile 
Если Вас интересуют double равные с заданной точностью, то Ваше решение с введением некоего эпсилон единственно возможное. Хотя, пожалуй еще возможно сравнение по относительной величине:
Код

    result = d1-d2;
    avg = (d1+d2)/2;
    epsilon = 0.000000001;
    if (result<-epsilon*avg) {
       //меньше
    }else if (resultЮepsilon*avg) {
       //больше
    } else {
       //равны
    }

Такой относительный подход предпочтительнее если Вы заранее не знаете порядка величин, поскольку если у Вас два числа порядка единицы дают разницу порядка 10^-15, то если Вы умножите оба своих числа на 10^20, то разность будет порядка 10^5.


--------------------
Mirkes
PM MAIL   Вверх
Pawl
Дата 13.11.2013, 12:39 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Опытный
**


Профиль
Группа: Участник
Сообщений: 649
Регистрация: 22.4.2008
Где: Витебск

Репутация: 7
Всего: 28



Цитата(Mirkes @  13.11.2013,  12:10 Найти цитируемый пост)
Хотя, пожалуй еще возможно сравнение по относительной величине

Да, хорошая мысль!


--------------------
В действительности всё совсем не так, как на самом деле
PM MAIL   Вверх
  
Ответ в темуСоздание новой темы Создание опроса
Правила форума "Java"
LSD   AntonSaburov
powerOn   tux
javastic
  • Прежде, чем задать вопрос, прочтите это!
  • Книги по Java собираются здесь.
  • Документация и ресурсы по Java находятся здесь.
  • Используйте теги [code=java][/code] для подсветки кода. Используйтe чекбокс "транслит", если у Вас нет русских шрифтов.
  • Помечайте свой вопрос как решённый, если на него получен ответ. Ссылка "Пометить как решённый" находится над первым постом.
  • Действия модераторов можно обсудить здесь.
  • FAQ раздела лежит здесь.

Если Вам помогли, и атмосфера форума Вам понравилась, то заходите к нам чаще! С уважением, LSD, AntonSaburov, powerOn, tux, javastic.

 
1 Пользователей читают эту тему (1 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | Java: Общие вопросы | Следующая тема »


 




[ Время генерации скрипта: 0.1272 ]   [ Использовано запросов: 21 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.