Как проверить, является ли double целым числом

166

Можно ли это сделать?

double variable;
variable = 5;
/* the below should return true, since 5 is an int. 
if variable were to equal 5.7, then it would return false. */
if(variable == int) {
    //do stuff
}

Я знаю , что код , вероятно , ничего подобного не идти, но как же оно делось?

JXPheonix
источник
1
C #, но похожий в Java: stackoverflow.com/a/4077262/284240 ( Integer.MAX_VALUE )
Тим Шмельтер,
1
Что бы вы получили от этого? doubleи intпредставлены в памяти по-разному, и вы будете использовать один или другой в зависимости от контекста обработки вашей памяти.
Макото
@ Легенда, я бы сделал то же самое, что вы предложили; Вы случайно не знаете, как% 1 сравнивает по эффективности с Math.floor (переменная), предложенная другими пользователями?
Г. Бах
3
@Makoto Это программа для поиска пигаторейских троек. Квадратные корни иногда могут быть двойными, но в то же время они также могут быть интергерами. Вы понимаете, о чем я?
JXPheonix
@JXPheonix: Значения могут быть значениями с плавающей точкой или целыми числами. Имеет смысл.
Макото

Ответы:

146
if ((variable == Math.floor(variable)) && !Double.isInfinite(variable)) {
    // integer type
}

Это проверяет, совпадает ли округленное значение double с двойным.

Ваша переменная может иметь значение типа int или double и Math.floor(variable)всегда иметь значение типа int, поэтому, если ваша переменная равна, Math.floor(variable)она должна иметь значение int.

Это также не работает, если значение переменной бесконечно или отрицательно бесконечно, следовательно, добавляя «пока переменная не бесконечна» к условию.

maxhud
источник
3
«Если аргумент равен NaN или бесконечности, или положительному нулю, или отрицательному нулю, то результат совпадает с аргументом». docs.oracle.com/javase/6/docs/api/java/lang/…
Тим
2
@TimSchmelter: хороший улов. Стоит также отметить, что NaN не равен ничему (включая себя), но +/- Inf равно самому себе - так что есть два крайних случая!
maerics
И Скон, и Фуад опубликовали гораздо лучшие ответы.
Джоэл Кристофел
@JoelChristophel: я не согласен. Это хороший способ, поскольку он устраняет риск переполнения типа. Единственное, что мне не понравилось, было утверждение, что переменная была intif, если ifоценивать true.
Вирсавия
@Bathsheba (Double.POSITIVE_INFINITY% 1) == 0 и его отрицательный аналог оба имеют значение false.
Джоэл Кристофель
223

Или вы можете использовать оператор по модулю:

(d % 1) == 0

SkonJeet
источник
2
Мне очень нравится простота этого решения. Это легко читать и реализовывать.
Криспи
1
Очень интуитивное решение
Даниэль Сан
3
С точки зрения вычислений, это быстрее, чем Math.rint(d)?
iTurki
2
Да, это хорошо, но обратите внимание, это решение Java, и оно не очень хорошо определено для отрицательного dв C и C ++.
Вирсавия
4
В Sonar возникает проблема «Тесты на равенство не должны выполняться со значениями с плавающей запятой».
Julio D
86

Гуава: DoubleMath.isMathematicalInteger. (Раскрытие: я написал это.) Или, если вы еще не импортируете Guava, x == Math.rint(x)это самый быстрый способ сделать это; rintзаметно быстрее, чем floorили ceil.

Луи Вассерман
источник
3
Не знал о математике. Ты прав. Это намного быстрее, чем Math.floor
Ленни Маркус
Является ли это как-то предпочтительнее примера кастинга Eng.Fouad?
Джоэл Кристофель
@JoelChristophel: Да. Не все числа типа double с целочисленными значениями находятся в диапазоне int или даже long, поэтому тест не будет работать с ними.
Луи Вассерман
Попался. Тогда (d% 1) == 0 все еще действует.
Джоэл Кристофель
20
public static boolean isInt(double d)
{
    return d == (int) d;
}
Eng.Fouad
источник
6

Попробуйте так,

public static boolean isInteger(double number){
    return Math.ceil(number) == Math.floor(number); 
}

например:

Math.ceil(12.9) = 13; Math.floor(12.9) = 12;

следовательно, 12.9 не является целым числом, тем не менее

 Math.ceil(12.0) = 12; Math.floor(12.0) =12; 

следовательно, 12.0 является целым числом

Шелдон
источник
3

Вот версия для Integerи Double:

    private static boolean isInteger(Double variable) {
    if (    variable.equals(Math.floor(variable)) && 
            !Double.isInfinite(variable)          &&
            !Double.isNaN(variable)               &&
            variable <= Integer.MAX_VALUE         &&
            variable >= Integer.MIN_VALUE) {
        return true;
    } else {
        return false;
    }
}

Чтобы преобразовать Doubleв Integer:

Integer intVariable = variable.intValue();
irudyak
источник
3

Рассматривать:

Double.isFinite (value) && Double.compare (value, StrictMath.rint (value)) == 0

Это прилипает к ядру Java и позволяет избежать сравнения на равенство между значениями с плавающей запятой ( ==), что представляется неверным. Это isFinite()необходимо, так как rint()будут проходить значения бесконечности.

simon.watts
источник
3

Лучший способ с оператором модуля

if(val % 1 == 0)
Абдул Хафиз Хан
источник
1
Можете ли вы добавить больше объяснений, чтобы ответить? Спасибо!
Шантешвар Инд
3

Вот хорошее решение:

if (variable == (int)variable) {
    //logic
}
Nitish
источник
почему (bool)актерский состав?
xdavidliu
1
@ xdavidliu В этом нет необходимости. Мы можем игнорировать это.
Нитиш
2

Аналогично ответу SkonJeet выше, но производительность лучше (по крайней мере, в Java):

Double zero = 0d;    
zero.longValue() == zero.doubleValue()
edwardsayer
источник
1
public static boolean isInteger(double d) {
  // Note that Double.NaN is not equal to anything, even itself.
  return (d == Math.floor(d)) && !Double.isInfinite(d);
}
maerics
источник
Более правильная реализация вернула бы false, и вам пришлось бы написать другой метод, который принимает int в качестве аргумента и возвращает true. : D
Альфа
0

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

public final double testRange = 0.2;

public static boolean doubleIsInteger(double d){
    int i = (int)d;
    double abs = Math.abs(d-i);
    return abs <= testRange;
}

Если вы присвоите d значение 33.15, метод вернет true. Чтобы получить лучшие результаты, вы можете назначить более низкие значения для testRange (как 0.0002) на ваше усмотрение.

Salvi94
источник
0

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

if (new BigDecimal(decimalValue).remainder(new BigDecimal(1)).equals(BigDecimal.ZERO)) {
    // no decimal places
} else {
    // decimal places
}

Remainder(BigDecimal)возвращает BigDecimalзначение которого является (this % divisor). Если это равно нулю, мы знаем, что с плавающей запятой нет.

chaeschuechli
источник
0

Мое простое решение:

private boolean checkIfInt(double 
 value){
 return value - Math.floor(value) == 0;
 }
Мостафа Амер
источник
-1

Вот решение:

float var = Your_Value;
if ((var - Math.floor(var)) == 0.0f)
{
    // var is an integer, so do stuff
}
МОХИТ ГУПТА
источник