Перейти к содержимому

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

  • автор:

Сравнение длинных значений в Java

В этом кратком руководстве мы обсудим различные способы сравнения двух экземпляров Long . Подчеркнем проблемы, возникающие при использовании оператора сравнения ссылок ( == ).

2. Проблема с использованием сравнения ссылок​

Long — это класс-оболочка для примитивного типа long . Поскольку они являются объектами, а не примитивными значениями, нам нужно сравнить содержимое экземпляров Long , используя .equals() вместо оператора сравнения ссылок (==).

В некоторых случаях нам может показаться, что == это нормально, но внешность обманчива. Учтите, что мы можем использовать == с меньшими числами:

 Long l1 = 127L;   Long l2 = 127L;    assertThat(l1 == l2).isTrue(); 

но не с большими числами. В конечном итоге у нас возникнут проблемы, если значения выходят за пределы диапазона от -128 до 127, что приведет к совершенно другому и неожиданному результату:

 Long l1 = 128L;   Long l2 = 128L;    assertThat(l1 == l2).isFalse(); 

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

3. Использование .equals() ​

Одним из решений является использование .equals() . Это оценит содержимое (а не ссылку) обоих объектов:

 Long l1 = 128L;   Long l2 = 128L;    assertThat(l1.equals(l2)).isTrue(); 

4. Объекты.равно() ​

Проблема с использованием equals() заключается в том, что нам нужно быть осторожными, чтобы не вызвать его для нулевой ссылки.

К счастью, есть служебный метод, безопасный для нулей, который мы можем использовать — Objects.equals () .

Посмотрим, как это работает на практике:

 Long l1 = null;   Long l2 = 128L;    assertThatCode(() -> Objects.equals(l1, l2)).doesNotThrowAnyException(); 

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

Под капотом Objects.equals() сначала используется оператор == для сравнения, а если это не удается, используется стандартный метод equals().

5. Распаковка длинных значений​

5.1. Использование метода .longValue() ​

Далее воспользуемся оператором сравнения «==», но безопасным способом. Класс Number имеет метод .longValue() , который разворачивает примитивное длинное значение:

 Long l1 = 128L;   Long l2 = 128L;    assertThat(l1.longValue() == l2.longValue()).isTrue(); 

5.2. Приведение к примитивным значениям​

Другой способ распаковать Long — привести объекты к примитивным типам. Поэтому мы извлечем примитивное значение, а затем сможем перейти к использованию оператора сравнения:

 Long l1 = 128L;   Long l2 = 128L;    assertThat((long) l1 == (long) l2).isTrue(); 

Обратите внимание, что для метода .longValue() или использования приведения мы должны проверить, является ли объект нулевым . У нас может быть исключение NullPointerException , если объект имеет значение null .

6. Заключение​

В этом коротком руководстве мы рассмотрели различные варианты сравнения длинных объектов. Мы проанализировали различия при сравнении ссылок на объекты или контент.

Как всегда, полный исходный код статьи доступен на GitHub .

  • 1. Обзор
  • 2. Проблема с использованием сравнения ссылок
  • 3. Использование .equals()
  • 4. Объекты.равно()
  • 5. Распаковка длинных значений
    • 5.1. Использование метода .longValue()
    • 5.2. Приведение к примитивным значениям

    Сравнение объектов: практика

    Java-университет

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

    Сравнение объектов: практика - 1

    • Сравнение строк: ‘ == ‘ и equals
    • Метод String.intern
    • Сравнение вещественных примитивов
    • +0.0 и -0.0
    • Значение NaN
    • Java 5.0. Производящие методы и сравнение через ‘ == ‘
    • Java 5.0. Autoboxing/Unboxing: ‘ == ‘, ‘ >= ‘ и ‘ ‘ для объектных оболочек.
    • Java 5.0. сравнение элементов перечислений (тип enum )

    Сравнение строк: ‘ == ‘ и equals

    Ах, эти строки. Один из наиболее часто используемых типов, вызывающих при этом немало проблем. В принципе, о них есть отдельная статья. А здесь я коснусь вопросов сравнения. Разумеется, строки можно сравнивать с помощью equals . Более того, их НУЖНО сравнивать через equals . Однако, есть тонкости, которые стоит знать. Прежде всего, одинаковые строки на самом деле являются единственным объектом. В чем легко убедиться, выполнив следующий код:

     String str1 = "string"; String str2 = "string"; System.out.println(str1==str2 ? "the same" : "not the same"); 

    Результатом будет «the same». Что означает, что ссылки на строки равны. Это сделано на уровне компилятора, очевидно, для экономии памяти. Компилятор создает ОДИН экземпляр строки, и присваивает str1 и str2 ссылку на этот экземпляр. Однако, это относится только к строкам, объявленным как литералы, в коде. Если скомпоновать строку из кусков, ссылка на нее будет другой. Подтверждение – данный пример:

     String str1 = "string"; String str2 = "str"; String str3 = "ing"; System.out.println(str1==(str2+str3) ? "the same" : "not the same"); 

    Результатом будет «not the same». Также можно создать новый объект с помощью копирующего конструктора:

     String str1 = "string"; String str2 = new String("string"); System.out.println(str1==str2 ? "the same" : "not the same"); 

    Результатом также будет «not the same». Таким образом, иногда строки можно сравнивать и через сравнение ссылок. Но на это лучше не полагаться. Я хотел бы затронуть один весьма любопытный метод, который позволяет получить так называемое каноническое представление строки – String.intern . Поговорим о нем поподробнее.

    Метод String.intern

    Начнем с того, что класс String поддерживает пул строк. В этот пул добавляются все строковые литералы, определенные в классах, и не только они. Так вот, метод intern позволяет получить из этого пула строку, которая равна имеющейся (той, у которой вызывается метод intern ) с точки зрения equals . Если такой строки в пуле не существует, то туда помещается имеющаяся, и возвращается ссылка на нее. Таким образом, если даже ссылки на две равных строки разные (как в двух примерах выше), то вызовы у этих строк intern вернут ссылку на один и тот же объект:

     String str1 = "string"; String str2 = new String("string"); System.out.println(str1.intern()==str2.intern() ? "the same" : "not the same"); 

    Результатом выполнения этого фрагмента кода будет «the same». Я не могу сказать точно, зачем это сделано так. Метод intern – native, а в дебри С-кода мне, честно сказать, не хочется. Скорее всего это сделано для оптимизации потребления памяти и производительности. В любом случае, стоит знать об этой особенности реализации. Переходим к следующей части.

    Сравнение вещественных примитивов

    Для начала я хочу задать вопрос. Очень простой. Чему равна следующая сумма – 0.3f + 0.4f? Чему? 0.7f? Проверим:

     float f1 = 0.7f; float f2 = 0.3f + 0.4f; System.out.println("f1==f2: "+(f1==f2)); 

    Как результат? Нравится? Мне тоже. Для тех, кто не выполнил этот фрагмент, скажу – результат будет.

     f1==f2: false 

    Почему это происходит. Выполним еще один тест:

     float f1 = 0.3f; float f2 = 0.4f; float f3 = f1 + f2; float f4 = 0.7f; System.out.println("f1="+(double)f1); System.out.println("f2="+(double)f2); System.out.println("f3="+(double)f3); System.out.println("f4 |f3-f4| 

    В этом случае результат вселяет надежду:

     |f3-f4| 

    Разумеется, точно та же картина и с типом double . С единственной разницей, что там на мантиссу отведено 53 бита, следовательно, точность представления – 2-53≈10-16. Да, величина квантования куда меньше, но она есть. И может сыграть злую шутку. Кстати, в тестовой библиотеке JUnit в методах сравнения вещественных чисел точность указывается в явном виде. Т.е. метод сравнения содержит три параметра – число, чему оно должно быть равно и точность сравнения. Еще кстати, хочу упомянуть о тонкости, связаной с записью чисел в научном формате, с указанием степени. Вопрос. Как записать 10-6? Практика показывает, что более 80% отвечают – 10e-6. Между тем, правильный ответ – 1e-6! А 10e-6 – это 10-5! Мы наступили на эти грабли в одном из проектов, довольно неожиданно. Ошибку искали очень долго, на константы смотрели раз 20. И ни у кого не возникло ни тени сомнения в их правильности, пока однажды, в большой степени случайно, константу 10e-3 не вывели на печать и не обнаружили у нее после запятой два знака вместо ожидавшихся трех. А потому – будьте бдительны! Движемся дальше.

    +0.0 и -0.0

    В представлении вещественных чисел старший бит является знаковым. А что будет, если все остальные биты равны 0? В отличие от целых, где в такой ситуации получается отрицательное число, находящееся на нижней границе диапазона представления, вещественное число только со старшим битом, выставленным в 1, тоже обозначает 0, только со знаком минус. Таким образом, у нас есть два нуля – +0.0 и -0.0. Возникает логичный вопрос – считать ли эти числа равными? Виртуальная машина считает именно так. Однако, это два разных числа, ибо в результате операций с ними получаются разные значения:

     float f1 = 0.0f/1.0f; float f2 = 0.0f/-1.0f; System.out.println("f1="+f1); System.out.println("f2="+f2); System.out.println("f1==f2: "+(f1==f2)); float f3 = 1.0f / f1; float f4 = 1.0f / f2; System.out.println("f3="+f3); System.out.println("f4 i1 (+0.0):"+ Integer.toBinaryString(i1)); System.out.println("i2 (-0.0):"+ Integer.toBinaryString(i2)); System.out.println("i1==i2: "+(i1 == i2)); 

    Результатом будет

     i1 (+0.0):0 i2 (-0.0):10000000000000000000000000000000 i1==i2: false 

    Таким образом, если у вас +0.0 и -0.0 – разные числа, то сравнивать вещественные переменные следует через их битовое представление. С +0.0 и -0.0 вроде как разобрались. -0.0, однако, является не единственным сюрпризом. Есть еще такое явление как.

    Значение NaN

    NaN расшифровывается как Not-a-Number . Это значение появляется в результате некорректных математических операций, скажем, деления 0.0 на 0.0, бесконечности на бесконечность и т.п. Особенностью этого значения является то, что оно не равно самому себе. Т.е.:

     float x = 0.0f/0.0f; System.out.println("x="+x); System.out.println("x==x: "+(x==x)); 

    . даст в результате.

     x=NaN x==x: false 

    Чем это может обернуться при сравнении объектов? Если поле объекта будет равно NaN , то сравнение даст false , т.е. объекты гарантированно будут считаться неравными. Хотя по логике вещей мы можем хотеть как раз обратного. Добиться нужного результата можно, используя метод Float.isNaN(float) . Он возвращает true , если аргумент – NaN . На сравнение битовых представлений я бы в этом случае не полагался, т.к. оно не стандартизовано. Пожалуй, о примитивах хватит. Перейдем теперь к тонкостям, появившимся в Java с версии 5.0. И первый момент, которого я бы хотел коснуться –

    Java 5.0. Производящие методы и сравнение через ' == '

    В проектировании есть шаблон, называемый производящий метод . Иногда его использование гораздо более выгодно, нежели использование конструктора. Приведу пример. Думаю, все хорошо знаю объектную оболочку Boolean . Этот класс неизменяемый, способен содержать всего два значения. Т.е., фактически, для любых нужд хватит всего-навсего двух экземпляров. И если их создать заранее, а потом просто возвращать, то это будет намного быстрее, чем использование конструктора. Такой метод у Boolean есть: valueOf(boolean) . Появился он в версии 1.4. Подобные же производящие методы были введены с версии 5.0 и в классах Byte , Character , Short , Integer и Long . При загрузке этих классов создаются массивы их экземпляров, соответствующие определенным диапазонам значений примитивов. Диапазоны эти следующие:

    Сравнение объектов: практика - 2

    Означает это, что при использовании метода valueOf(. ) при попадании аргумента в указанный диапазон всегда будет возвращаться один и тот же объект. Возможно, это и дает какое-то увеличение скорости. Но при этом появляются проблемы такого характера, что докопаться до сути бывает довольно сложно. Читайте об этом дальше. Теоретически производящий метод valueOf добавлен и в классы Float и Double . В их описании сказано, что если не нужен новый экземпляр, то лучше пользоваться этим методом, т.к. он может дать прибавку в скорости и т.д. и т.п. Однако в текущей (Java 5.0) реализации в этом методе создается новый экземпляр, т.е. прибавки в скорости его использование не даст гарантированно. Более того, мне сложно представить, как можно ускорить этот метод, ибо ввиду непрерывности значений кеш там не организуешь. Разве что для целых чисел. В смысле, без дробной части.

    Java 5.0. Autoboxing/Unboxing: ' == ', ' >= ' и ' ' для объектных оболочек.

    Подозреваю, что производящие методы и кеш экземпляров были добавлены в оболочки для целочисленных примитивов ради оптимизации операций autoboxing/unboxing . Напомню, что это такое. Если в операции должен участвовать объект, а участвует примитив, то этот примитив автоматически оборачивается в объектную оболочку. Это autoboxing . И наоборот – если в операции должен участвовать примитив, то можно подставить туда объектную оболочку, и значение будет автоматически из нее развернуто. Это unboxing . Естественно, за такое удобство надо платить. Операции автоматического преобразования несколько замедляют скорость работы приложения. Однако к текущей теме это не относится, потому оставим этот вопрос. Все хорошо до тех пор, пока мы имеем дело с операциями, однозначно относящимися к примитивам либо к оболочкам. А что будет с операцией ' == '? Допустим, у нас есть два объекта Integer , с одинаковым значением внутри. Как они будут сравниваться?

     Integer i1 = new Integer(1); Integer i2 = new Integer(1); System.out.println("i1==i2: "+(i1==i2)); 
     i1==i2: false Кто бы сомневался. Сравниваются они как объекты. А если так: Integer i1 = 1; Integer i2 = 1; System.out.println("i1==i2: "+(i1==i2)); 
     i1==i2: true 

    Вот это уже интереснее! При autoboxing -е возвращаются одинаковые объекты! Вот тут и находится ловушка. Однажды обнаружив, что возвращаются одинаковые объекты, мы начнем экспериментировать, чтобы проверить, всегда ли это так. И сколько мы проверим значений? Одно? Десять? Сто? Скорее всего ограничимся сотней в каждую сторону вокруг нуля. И везде получим равенство. Казалось бы, все хорошо. Однако, посмотрите чуть назад, вот сюда. Догадались, в чем подвох. Да, экземпляры объектных оболочек при autoboxing-е создаются с помощью производящих методов. Что хорошо иллюстрируется следующим тестом:

     public class AutoboxingTest < private static final int numbers[] = new int[]; public static void main(String[] args) < for (int number : numbers) < Integer i1 = number; Integer i2 = number; System.out.println("number=" + number + ": " + (i1 == i2)); >> > 

    Результат будет таков:

     number=-129: false number=-128: true number=127: true number=128: false 

    Для попадающих в диапазон кеширования значений возвращаются одинаковые объекты, для находящихся вне него – разные. А следовательно, если где-то в приложении будут сравниваться оболочки вместо примитивов – есть шанс получить самую страшную ошибку: плавающую. Потому как тестировать код, скорее всего, тоже будут на ограниченом диапазоне значений, в котором эта ошибка не проявится. А в реальной работе она то будет проявляться, то исчезать, в зависимости от результатов каких-то вычислений. Проще сойти с ума, чем найти такую ошибку. А потому – я бы советовал избегать autoboxing-а где только можно. И это не всё. Вспомним математику, не далее чем 5-го класса. Пусть выполняются неравенства A>=B и А . Что можно сказать об отношении A и B ? Только одно – они равны. Согласны? Думаю, да. Запускаем тест:

     Integer i1 = new Integer(1); Integer i2 = new Integer(1); System.out.println("i1>=i2: "+(i1>=i2)); System.out.println("i1 

    Результат:

     i1>=i2: true i1 

    И вот это для меня – самая большая странность. Я вообще не понимаю, зачем было вводить в язык эту возможность, если она вносит такие противоречия. В общем, повторю еще раз – если есть возможность обойтись без autoboxing/unboxing , то стоит эту возможность использовать на полную катушку. Последняя тема, которой я хотел бы коснуться, это. Java 5.0. сравнение элементов перечислений (тип enum) Как известно, с версии 5.0 в Java появился такой тип как enum – перечисление. Его экземпляры по умолчанию содержат имя и порядковый номер в объявлении экземпляра в классе. Соответственно, при изменении порядка объявления номера меняются. Однако, как я уже говорил в статье 'Сериализация как она есть', это не вызывает проблем. Все элементы перечисления существуют в единственном экземпляре, это контролируется на уровне виртуальной машины. Поэтому их можно сравнивать напрямую, по ссылкам. * * * Пожалуй, это всё на сегодня о практической стороне реализации сравнения объектов. Возможно, я что-то упустил. Как обычно, жду комментариев! А пока позвольте откланяться. Всем спасибо за внимание! Ссылка на первоисточник: Сравнение объектов: практика

    13.2. Java – Метод compareTo()

    Метод compareTo() – сравнивает числовой объект, который вызывает метод, с аргументом. При работе с числами метод compareTo() в Java позволяет сравнить два числа одного типа, например, byte, long, integer и т.д. Однако нельзя сравнивать два разных типа аргумента и числового объекта, вызывая метод они должны быть одного типа.

    Синтаксис

    public int compareTo( NumberSubClass referenceName ) 

    Параметры

    Подробная информация о параметрах:

    • referenceName – должно быть byte, double, integer, float, long или short.

    Возвращаемое значение

    • Если Integer равно аргументу, то возвращается 0.
    • Если Integer меньше, чем аргумент, то возвращается -1.
    • Если Integer больше, чем аргумент, то возвращается 1.

    Пример

    public class Test < public static void main(String args[])< Integer x = 5; System.out.println(x.compareTo(3)); System.out.println(x.compareTo(5)); System.out.println(x.compareTo(8)); >> 

    Будет получен следующий результат:

    1 0 -1 

    Оглавление

    • 1. Java – Самоучитель для начинающих
    • 2. Java – Обзор языка
    • 3. Java – Установка и настройка
    • 4. Java – Синтаксис
    • 5. Java – Классы и объекты
    • 6. Java – Конструкторы
    • 7. Java – Типы данных и литералы
    • 8. Java – Типы переменных
    • 9. Java – Модификаторы
    • 10. Java – Операторы
    • 11. Java – Циклы и операторы цикла
    • 11.1. Java – Цикл while
    • 11.2. Java – Цикл for
    • 11.3. Java – Улучшенный цикл for
    • 11.4. Java – Цикл do..while
    • 11.5. Java – Оператор break
    • 11.6. Java – Оператор continue
    • 12. Java – Операторы принятия решений
    • 12.1. Java – Оператор if
    • 12.2. Java – Оператор if..else
    • 12.3. Java – Вложенный оператор if
    • 12.4. Java – Оператор switch..case
    • 12.5. Java – Условный оператор (? 🙂
    • 13. Java – Числа
    • 13.1. Java – Методы byteValue(), shortValue(), intValue(), longValue(), floatValue(), doubleValue()
    • 13.2. Java – Метод compareTo()
    • 13.3. Java – Метод equals()
    • 13.4. Java – Метод valueOf()
    • 13.5. Java – Метод toString()
    • 13.6. Java – Метод parseInt()
    • 13.7. Java – Метод Math.abs()
    • 13.8. Java – Метод Math.ceil()
    • 13.9. Java – Метод Math.floor()
    • 13.10. Java – Метод Math.rint()
    • 13.11. Java – Метод Math.round()
    • 13.12. Java – Метод Math.min()
    • 13.13. Java – Метод Math.max()
    • 13.14. Java – Метод Math.exp()
    • 13.15. Java – Метод Math.log()
    • 13.16. Java – Метод Math.pow()
    • 13.17. Java – Метод Math.sqrt()
    • 13.18. Java – Метод Math.sin()
    • 13.19. Java – Метод Math.cos()
    • 13.20. Java – Метод Math.tan()
    • 13.21. Java – Метод Math.asin()
    • 13.22. Java – Метод Math.acos()
    • 13.23. Java – Метод Math.atan()
    • 13.24. Java – Метод Math.atan2()
    • 13.25. Java – Метод Math.toDegrees()
    • 13.26. Java – Метод Math.toRadians()
    • 13.27. Java – Метод Math.random()
    • 14. Java – Символы
    • 14.1. Java – Метод Character.isLetter()
    • 14.2. Java – Метод Character.isDigit()
    • 14.3. Java – Метод Character.isWhitespace()
    • 14.4. Java – Метод Character.isUpperCase()
    • 14.5. Java – Метод Character.isLowerCase()
    • 14.6. Java – Метод Character.toUpperCase()
    • 14.7. Java – Метод Character.toLowerCase()
    • 14.8. Java – Метод Character.toString()
    • 15. Java – Строки
    • 15.1. Java – Метод charAt()
    • 15.2. Java – Метод compareTo()
    • 15.3. Java – Метод compareToIgnoreCase()
    • 15.4. Java – Метод concat()
    • 15.5. Java – Метод contentEquals()
    • 15.6. Java – Метод copyValueOf()
    • 15.7. Java – Метод endsWith()
    • 15.8. Java – Метод equals()
    • 15.9. Java – Метод equalsIgnoreCase()
    • 15.10. Java – Метод getBytes()
    • 15.11. Java – Метод getChars()
    • 15.12. Java – Метод hashCode()
    • 15.13. Java – Метод indexOf()
    • 15.14. Java – Метод intern()
    • 15.15. Java – Метод lastIndexOf()
    • 15.16. Java – Метод length()
    • 15.17. Java – Метод matches()
    • 15.18. Java – Метод regionMatches()
    • 15.19. Java – Метод replace()
    • 15.20. Java – Метод replaceAll()
    • 15.21. Java – Метод replaceFirst()
    • 15.22. Java – Метод split()
    • 15.23. Java – Метод startsWith()
    • 15.24. Java – Метод subSequence()
    • 15.25. Java – Метод substring()
    • 15.26. Java – Метод toCharArray()
    • 15.27. Java – Метод toLowerCase()
    • 15.28. Java – Метод toString()
    • 15.29. Java – Метод toUpperCase()
    • 15.30. Java – Метод trim()
    • 15.31. Java – Метод valueOf()
    • 15.32. Java – Классы StringBuilder и StringBuffer
    • 15.32.1. Java – Метод append()
    • 15.32.2. Java – Метод reverse()
    • 15.32.3. Java – Метод delete()
    • 15.32.4. Java – Метод insert()
    • 15.32.5. Java – Метод replace()
    • 16. Java – Массивы
    • 17. Java – Дата и время
    • 18. Java – Регулярные выражения
    • 19. Java – Методы
    • 20. Java – Потоки ввода/вывода, файлы и каталоги
    • 20.1. Java – Класс ByteArrayInputStream
    • 20.2. Java – Класс DataInputStream
    • 20.3. Java – Класс ByteArrayOutputStream
    • 20.4. Java – Класс DataOutputStream
    • 20.5. Java – Класс File
    • 20.6. Java – Класс FileReader
    • 20.7. Java – Класс FileWriter
    • 21. Java – Исключения
    • 21.1. Java – Встроенные исключения
    • 22. Java – Вложенные и внутренние классы
    • 23. Java – Наследование
    • 24. Java – Переопределение
    • 25. Java – Полиморфизм
    • 26. Java – Абстракция
    • 27. Java – Инкапсуляция
    • 28. Java – Интерфейсы
    • 29. Java – Пакеты
    • 30. Java – Структуры данных
    • 30.1. Java – Интерфейс Enumeration
    • 30.2. Java – Класс BitSet
    • 30.3. Java – Класс Vector
    • 30.4. Java – Класс Stack
    • 30.5. Java – Класс Dictionary
    • 30.6. Java – Класс Hashtable
    • 30.7. Java – Класс Properties
    • 31. Java – Коллекции
    • 31.1. Java – Интерфейс Collection
    • 31.2. Java – Интерфейс List
    • 31.3. Java – Интерфейс Set
    • 31.4. Java – Интерфейс SortedSet
    • 31.5. Java – Интерфейс Map
    • 31.6. Java – Интерфейс Map.Entry
    • 31.7. Java – Интерфейс SortedMap
    • 31.8. Java – Класс LinkedList
    • 31.9. Java – Класс ArrayList
    • 31.10. Java – Класс HashSet
    • 31.11. Java – Класс LinkedHashSet
    • 31.12. Java – Класс TreeSet
    • 31.13. Java – Класс HashMap
    • 31.14. Java – Класс TreeMap
    • 31.15. Java – Класс WeakHashMap
    • 31.16. Java – Класс LinkedHashMap
    • 31.17. Java – Класс IdentityHashMap
    • 31.18. Java – Алгоритмы Collection
    • 31.19. Java – Iterator и ListIterator
    • 31.20. Java – Comparator
    • 32. Java – Дженерики
    • 33. Java – Сериализация
    • 34. Java – Сеть
    • 34.1. Java – Обработка URL
    • 35. Java – Отправка Email
    • 36. Java – Многопоточность
    • 36.1. Java – Синхронизация потоков
    • 36.2. Java – Межпоточная связь
    • 36.3. Java – Взаимная блокировка потоков
    • 36.4. Java – Управление потоками
    • 37. Java – Основы работы с апплетами
    • 38. Java – Javadoc

    Как сравнить long в 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 нужно сравнить особым образом". Почему бы их не сравнить как другие числа? Типа из-за того, что на каких-то там мегавеличинах будет неточность?

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

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

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