Как сравнить double java
Перейти к содержимому

Как сравнить double java

Как правильно сравнивать double в java

При сравнении значений типа double в Java следует быть осторожным из-за того, что внутреннее представление чисел с плавающей точкой может быть не точным. Например, значения, которые должны быть равными, могут отличаться на очень малое значение.

Вместо использования операторов == или != для сравнения значений типа double рекомендуется использовать методы класса Double , такие как equals() или compare() , которые предоставляют более точный способ сравнения чисел с плавающей точкой.

double d1 = 0.1 + 0.2; double d2 = 0.3; if (Double.valueOf(d1).equals(Double.valueOf(d2)))  System.out.println("d1 и d2 равны"); > 

В этом примере мы сравниваем два значения типа double , которые должны быть равными. Для сравнения используем метод equals() , который возвращает true , если значения равны, и false в противном случае.

Для сравнения двух значений типа double по их относительной близости друг к другу используйте метод compare() :

double d1 = 0.1 + 0.2; double d2 = 0.3; if (Double.compare(d1, d2) == 0)  System.out.println("d1 и d2 близки"); > 

Этот метод возвращает 0, если значения равны, 1, если первое значение больше второго, и -1, если первое значение меньше второго. Мы проверяем, равны ли значения, используя == 0

Как сравнивать double java

Сравнение значений типа double в Java может быть несколько запутанным из-за погрешности вычислений с плавающей точкой. Рекомендуется сравнивать значения типа double с использованием заранее заданного уровня точности:

double x = 1.234; double y = 1.235; double epsilon = 0.0001; // уровень точности if (Math.abs(x - y)  epsilon)  System.out.println("Значения равны"); > else  System.out.println("Значения не равны"); > 

Здесь мы используем метод Math.abs() , чтобы получить абсолютное значение разницы между x и y . Если это значение меньше заданного уровня точности epsilon , мы считаем, что x и y равны. В противном случае они не равны.

Как сравнить double java

Есть лаба где надо сравнить long и double. При проверке подсказали что long сравнивать с long, long и double нужно сравнить особым образом, все остальные типы приводить к double. Вопрос следующий почему long и double нужно сравнить особым образом? К BigDecimal приводить неверно .

Long.compareTo(x, y)
Добавьте уже новую секцию — java
Хотя просто compare(x, y)
(1) не верно, оба числа должны быть лонг, а тут лонрг и дабл, ты обертку от лонга используешь
(3) просто компайр не бывает

(4) продвижение типов, не?

double val1 = 1.0;
long val2 = (long) val1;

лонг меньше дабл, почему к его к даблу привести вообще не понятно, ошибка может произойти если long_maxvalue. Все равно не понятно как

(6) это косяк сильный, привести дабл к лонг, наоборот можно
(6)
double val1 = 1.5;
long val2 = (long) val1; // равно 1

(9) это понятно, я смотрю на (1)

так как их сравнивать-то «правильно»? Мне вот совсем непонятно, почему их нужно сравнивать как-то по особенному, а не продвигать один тип к другому?

Правильно будет так

long val1 = 1;
double val2 = (double) val1;

«long и double нужно сравнить особым образом, все остальные типы приводить к double»

Так почему long не привести к double?

(11) и я уже все перечитал, не вижу проблемы. цитата «в таком случае у тебя не сработает Long.MAX_VALUE» вот подсказка от проверяющего

(13) походу надо как-то через классы-обёртки сравнивать

(9) double превышает long на много-много порядоков, так как внутри пишется в экспоненциальной форме (много статей в инете о представление плавающей точки на уровне железа). И соответственно у тебя может быть усечение значения.
Более правильно кстати тогда не Long.compare(x,y) брать а Dobule.compare(x,y), хотя на самом деле они оба реализуются на машинном уровне а не байткодом.

(15) я в (9) показал ошибку из другого сообщения, это понятно. Проблема в том что проверяющий не сичтает что перевод в дабл правильное решение. см (13)

jshell> double a = Double.valueOf(Long.MAX_VALUE)
a ==> 9.223372036854776E18

jshell> long b = Long.MAX_VALUE
b ==> 9223372036854775807

jshell> Double.compare(a, b)
$3 ==> 0

(17) А попробуй тоже самое, но long b = Long.MAX_VALUE — 1;
(2) Salesforce

(18) Выдаст точно то же самое:
jshell> double a = Double.valueOf(Long.MAX_VALUE — 1)
a ==> 9.223372036854776E18

jshell> long b = Long.MAX_VALUE
b ==> 9223372036854775807

jshell> Double.compare(a, b)
$3 ==> 0

Просто нужно уяснить что в Double в принципе не может храниться 9223372036854775806 (Long.MAX_VALUE — 1).
происходит потеря точности:

jshell> double d = 9223372036854775806.0
d ==> 9.223372036854776E18

+(20)
jshell> Double d = 9223372036854775806.0
d ==> 9.223372036854776E18

jshell> d.longValue()
$4 ==> 9223372036854775807

+(21)
jshell> Double d = 9.223372036854775E18
d ==> 9.2233720368547748E18

jshell> d.longValue()
$14 ==> 9223372036854774784

Таким образом double может хранить ближайшие числа

9223372036854774784 и 9223372036854775807

(20) напиши как правильно сравнить, пока примерно понятно

(23) Так я и написал Double.compare(x,y)
То что у тебя long будет к примеру Long.MAX_VALUE — 1 оно и будет либо меньше Double.valueOf(Long.MAX_VALUE) либо больше 9223372036854774784. А между этими значениями просто double просто не может содержать значений, ему физически разрядов не хватает для такой точности.

(24) большое тебе спасибо ! ты 1С ник ?
(24) лонги надо сравнивать между собой, а остальные сравнивать через дабл

Короче если по тупому то можно в long засунуть такое число, которое при переносе в double потеряет свою точность.
В то время как классические int прекрасно переносятся и сравниваются с double.

Чтобы сравнить long и double надо знать точность представления типа double на конкретной платформе и привести (округлить) значение.

(27) с точки зрения теории я тебя понимаю, а как на практике это реализовать. На ссылке JavaRush предлагают использовать DigDecimal

вот что получилось

long l1;
long l2;
double d1;
double d2;

if (num1 instanceof Long && num2 instanceof Long)

return Long.compare(l1, l2);

> else if ((num1 instanceof Long && num2 instanceof Double) || (num1 instanceof Double && num2 instanceof Long)) <
// можно в long засунуть такое число, которое при переносе в double потеряет свою точность

BigDecimal b1 = new BigDecimal(«» + num1);

BigDecimal b2 = new BigDecimal(«» + num2);

d1 = num1.doubleValue();
d2 = num2.doubleValue();
return Double.compare(d1, d2);
>

и это ваш великий джава?
2 числа сравнить не может. даже паскаль умеет.
(29) static int compare(T num1, V num2)
Хороший язык java.
Надёжный и простой, как Швейцарские часы.

(33) просто здесь сравнивается класс Number, надеюсь так не используется. Лучше типизировать без компараторов.

(33) — вы так говорите, как будто по ха пе лучше
(35) ты что делфи же лучше всех
(35) фузина зе бэст
(29) вместо преобразования через строку лучше делать
BigDecimal b1 = BigDecimal.valueOf(num1);
(38) сейчас гляну
(38) он так не умеет, по сути я сделал тоже самое только из строки
(38) Проще floatValue() и сравнивать с long
(40) как это не умеет?
https://www.geeksforgeeks.org/bigdecimal-valueof-method-in-java/
(0) Equals предлогали?

так это,мантисса double, это 53 бита,а long это 64
просто,внезапно,регистр сопроцессора это 80 бит и там 64 бита на мантиссу есть,т.к. длинные целые как раз 64 бита.
но типа long double во многих языках нет.

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

(30) в жабе ещё много чудес есть
(0) читайте про приведение типов

Академические задачи такие академические. Кто-нибудь может мне рассказать практический смысл сей задачи?

(47) просто челу лень книжки читать

Пункт Первый. Java самый лучший язык в мире.
Пункт второй. Если пункт первый не верен, goto Пункт Первый.

(48) дело не в топикстартере, а в «long и double нужно сравнить особым образом». Почему бы их не сравнить как другие числа? Типа из-за того, что на каких-то там мегавеличинах будет неточность?

ты только представь себе размеры. Вот если будет задача учёта всех звёзд во вселенной. ну бред же какой-то.

Быстрое сравнение double

Вчера здесь вышла статья о быстром парсинге double, я зашёл во блог к её автору, и нашёл там ещё один интересный трюк. При сравнении чисел с плавающей точкой особое внимание приходится уделять NaN (восемь лет назад я писал про них подробнее); но если сравниваемые числа заведомо не NaN, то сравнить их можно быстрее, чем это делает процессор!

Положительные double сравнивать очень просто: нормализация гарантирует нам, что из чисел с разной экспонентой больше то, чья экспонента больше, а из чисел с равной экспонентой больше то, чья мантисса больше. Стандарт IEEE 754 заботливо поместил экспоненту в старшие биты, так что положительные double можно сравнивать просто как int64_t.

С отрицательными числами немного сложнее: они хранятся в прямом коде, тогда как int64_t — в дополнительном. Это значит, что для использования целочисленного сравнения младшие 63 бита double необходимо инвертировать (при этом получится -0. < +0., что не соответствует стандарту, но на практике не представляет проблемы). Явная проверка старшего бита и условный переход уничтожили бы всю выгоду от перехода к целочисленному сравнению; но есть способ проще!

inline int64_t to_int64(double x) < int64_t a = *(int64_t*)&x; uint64_t mask = (uint64_t)(a >> 63) >> 1; return a ^ mask; > inline bool is_smaller(double x1, double x2)

a>>63 заполняет все 64 бита копиями знакового бита, и затем >>1 обнуляет старший бит.

Во блоге у Daniel Lemire несколько другой код (той же вычислительной сложности), но мой вариант сохраняет то полезное свойство, что to_int64(0.) == 0

  • Высокая производительность
  • Ненормальное программирование
  • C

Добавить комментарий

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