Извлечение целых чисел из HashSet<Double>

У меня есть HashSet<Double>, из которого я хочу извлечь те элементы, которые являются целыми числами, т.е. те элементы, у которых все нули после запятой. Есть ли стандартный способ сделать это? Я мог бы сделать что-то окольное, например: учитывая двойное x, я могу посмотреть на все значения после десятичной точки и увидеть, все ли они равны нулю, но это кажется запутанным.

Вам придется сделать что-то обходное, потому что для JVM любое двойное значение является двойным значением, и она не проверяет, достаточно ли близко такое значение к целому числу.

NomadMaker 13.12.2020 09:23

Имейте в виду, что большие double числа не имеют достаточной точности, чтобы определить, было ли предназначено целое число.

Ole V.V. 13.12.2020 10:02

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

Ole V.V. 13.12.2020 10:33
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
0
3
212
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Ответ принят как подходящий

вы можете преобразовать их в целое число и приравнять приведенное значение к исходному

double d = 1.5;
if ((int)d==d) // integer
else // not integer

Работает только в диапазоне int. Я предполагаю, что 2_147_483_649.0 (также пишется 2.147483649E9) считается целым числом, но ваше условие if оценивается как ложное.

Ole V.V. 13.12.2020 10:09

да. но вы можете сделать то же самое с BigDecimal и сравнить его с bigDecimal.toBigInteger()

ATP 13.12.2020 10:37

Вы можете сделать что-то вроде этого:

HashSet<Double> hd = new HashSet<> ();
hd.add (3.5);
hd.add (2.0);
hd.add (3.444);
hd.add (-1.0);
Set<Double> filtered = hd.stream()
                         .filter (x -> (int)(double)x == x)
                         .collect (Collectors.toSet());
System.out.println (filtered);

Выход:

[2.0, -1.0]

Сначала вы должны привести Double к double, а затем к int. Если этот int равен исходному Double, этот Double имеет целочисленное значение.

Если вы хотите избежать явного приведения, вы можете изменить

.filter (x -> (int)(double)x == x)

к

.filter (x -> x.intValue() == x)

который делает то же самое.

"Кастинг" Double на double? Это звучит очень подозрительно для меня; конечно, это приведет к (автоматической) распаковке, но правильный способ сделать это — привести неупакованное двойное значение ((int)x.doubleValue()). И если мы уже говорим об этом: сравнение ``ìntwith a Double``` работает из-за автораспаковки, но чтобы сделать это действительно правильно, сделайте это: x.intValue() == x.doubleValue().

tquadrat 13.12.2020 09:53

@tquadrat приведение Double к double требуется, так как вы не можете напрямую привести Double к int. Да, приведение Double к double эквивалентно x.doubleValue(). «Правильный путь» — это вопрос мнения. Я думаю, что x.intValue() == x выглядит лучше, и да, это работает благодаря автоматической распаковке.

Eran 13.12.2020 09:59

– Да, нужно преобразовать Double в double, но это не «приведение», это «распаковка»… и обычно делается вызовом метода Double::doubleValue(), либо явно, либо неявно, как автораспаковка…

tquadrat 13.12.2020 10:03

Я думаю, вам нравится иметь окончательный результат целых чисел, а не двойников. Например. 7, а не 7.0.

Итак, попробуйте этот:

    Set<Double> set = new HashSet<>();
    set.add(6.4);
    set.add(10.44);
    set.add(7.0);

    Set<Integer> filtered = set.stream()
            .filter(item -> Math.floor(item) == item)
            .map(Double::intValue)
            .collect(Collectors.toSet());

    System.out.println(filtered);

Попробуй это:

Collection<Integer> filterIntegers( final HashSet<Double> doubles )
{
    final var retValue = doubles.stream()
        .filter( d -> d.doubleValue() == d.intValue() )
        .map( Double::intValue )
        .collect( Collector.toSet() );
    return retValue;
}

Явное сравнение действительного (двойного) значения d с его целым значением кажется мне наиболее точной реализацией требования. Никаких переборов, никаких математических операций (хотя все это дает одинаковые результаты!).

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