Как в Java сравнить 2 вещественных числа на равенство? — java

1 Звезда2 Звезды3 Звезды4 Звезды5 Звезд
Загрузка...

Вопрос:


У меня есть 2 вещественных числа, например типа double. Я хочу их сравнить на равенство с заданной точность. Как правильно выполнять такое сравнение?

Пока в голову приходит такой вариант:

double x, y;
...
public boolean isEqual(double x, double y, double eps){
    return Math.abs(x-y) < eps;
}

Кажется, что в Java должны быть встроенные способы сравнить 2 вещественных числа. Такие существуют?

Автор вопроса: Viktorov

Suvitruf

Вообще, это довольно интересный вопрос.

Да, в общем случае всегда рекомендуется использовать что-то вроде:

bool isEqual = fabs(a1 – a2) <= epsilon;

Но более интересный вопрос, какое значение для epsilon использовать.

К примеру, в C++ в float.h есть константа FLT_EPSILON, равная 1E-5. Всё, можно такое же значение использовать, да?

Вполне, если числа большие. Но если у вас число в промежутке [0;1], то начинаются проблемы. Точность вычисления будет соизмерима с фактическим значением, что приведёт к тому, что на такое сравнение нельзя будет положиться.

Относительный эпсилон

Для сравнения чисел можно руководствоваться правилом:

Для сравнения a1 и a2 вычисляем diff = fabs(a1-a2). Если diff меньше
,чем n% от max(abs(a1), abs(a2)), тогда a1 и a2 можно считать равными.

public static bool almostEqualRelative(float a, float b,
                         float maxRelDiff = FLT_EPSILON) {
    // находим разницу
    float diff = fabs(a - b);
    A = fabs(a);
    B = fabs(b);
    // находим большее
    float largest = (b > a) ? b : a;

    if (diff <= largest * maxRelDiff)
        return true;

    return false;
}

Более сложно и подробней про это можно почитать в этой занятной статье.

Можно использовать класс BigDecimal. Пример :

BigDecimal decimal = new 
BigDecimal("0.58499999999999996447286321199499070644378662109375");
BigDecimal decimal2 = new 
BigDecimal("0.58499999999999996447286321199499070644378662109374");

System.out.println(decimal.compareTo(decimal2));

Double x  = 0.58499999999999996447286321199499070644378662109375;
Double y = 0.58499999999999996447286321199499070644378662109374;

System.out.println(x>y);

Вывод:

  • 1
  • false

Источник

Вам также может быть интересно:

Использование вложенных маршрутов в React Router — javascript reactjs react-router
Вопрос: Для организации маршрутов в приложении использую React Router. <Route path="/" component={...}> <IndexRoute component={...}/> <Route path="user/:userId" component={...}> ...
Как с помощью Retrofit 2.0 отправить данные в JSON на сервер и получить ответ? — java android retrofit
Вопрос: Только начал читать про Retrofit 2.0 до этого использовал HttpURLConnection. Как я работаю с HttpURLConnection, формирую Json перевожу его в byte, ставлю header в ...
Не приходят push уведомления. FCM — android firebase android-notification
Вопрос: Появилась необходимость реализовать push уведомления. Прописал в манифесте сервис: <service android:name=".MyFirebaseMessagingService"> <intent-filter> ...
Принцип браузерной игры в линукс терминале — java linux terminal
Вопрос: Наткнулся на Java библиотеку CHARVA. И хотел бы уточнить у знающих людей, возможно ли на основе данной библиотеки сделать программу по принципу браузерной игры, но ...
Мерцание заблокированного экрана при выключенной подсветке в Debian 8 Gnome 3 — linux debian экран
Вопрос: На ноутбуке с Debian 8 Jessie и Gnome 3 имеется следующая проблема. При выключенном заблокированном экране сквозь него можно наблюдать, как весь экран становится белым, ...
Создание WCF клиента на готовый SOAP web сервер — c# wcf
Вопрос: Доброго времени суток. Появилась задача опрашивать web сервер с клиента на котором планируется написать WCF клиентскую часть. Информации про сервер очень мало (не знаю платформу ...
Безопасно ли удалить файл логов general_log.txt? — mysql
Вопрос: При выполнении запроса со вставкой данных большого объёма SQLyog начал вылетать с ошибкой: not enough memory application terminated В связи с этим я решила ...
Callback функции создания таблицы mysql в nodejs — mysql node.js callback
Вопрос: Есть функция, которая при запуске создает базу даных, function showDb() { pool.query("show databases like 'bt' ",function (err, ...
Как создать Adapter с неограниченным количеством строк и с неограниченным разным количеством столбцов в каждой строке — java android
Вопрос: Как создать Adapter с неограниченным количеством строк и с неограниченным разным количеством столбцов в каждой строке Автор вопроса: Salut Amigo Источник
Не могу передать байтовый массив в контроллер — c# asp.net-mvc entity-framework
Вопрос: У меня изображения храняться в бд в формате байтового массива, через форич отлично все выводит, но когда я хочу открыть страницу для работы с ...
proguard release error — java android mvp
Вопрос: Включил в проекте proguard, apk собирается, все хорошо, но приложение не работает) Proguard-rules.pro -keepattributes InnerClasses -keepattributes EnclosingMethod -keepattributes *Annotation* -dontoptimize # Keep Butterknife -keep class butterknife.** { *; } -dontwarn butterknife.internal.** -keep ...
Не отрабатывает page:update — javascript ruby-on-rails
Вопрос: Есть мой учебный проект на ruby. Делаю редактирование объектов с помощью JS. Сейчас работает так: Редактирую первый раз - всё нормально. Не обновляя страницу, ...
Как найти определенный символ в строке и удалить значение после него (и вместе с ним) Jquery — javascript html jquery
Вопрос: Здравствуйте, есть определенный набор строк, типа "L / Красный / 12345", как можно на странице найти их, и вырезать из них все что находится ...
Почему не работает wildcard module declaration? — typescript
Вопрос: Почему не работает такой способ декларации: declare module "*!text" {} ? Цель - использовать контент файла в переменной: import layout = require("/js/views/layouts/wnd.html!text"); или так: import layout from "/js/views/layouts/wnd.html!text"; Если ...
Как прервать 3rd-party код? — c# многопоточность .net-core
Вопрос: Есть 3rd-party код из библиотеки который "зависает" в ожидании где-то в работе с сетью. CancellationToken поддержки нет, таймаутов нет. Запускаю я его через: Task.Run(() => ...

Оставьте ответ

Ваш e-mail не будет опубликован. Обязательные поля помечены *