Як перевірити, чи є двійник цілим числом


165

Чи можна це зробити?

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
}

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


1
C # , але схоже на Java: stackoverflow.com/a/4077262/284240 ( Integer.MAX_VALUE )
Тім Schmelter

1
Що ви отримаєте від цього? doubleі intпредставлені в пам'яті по-різному, і ви б використовували те чи інше, виходячи з контексту обробки пам'яті.
Макото

@Legend, я зробив би те саме, що ти запропонував; чи випадково ви знаєте, як% 1 порівнює ефективність роботи з запропонованими іншими користувачами Math.floor (змінною)?
Г. Бах

3
@Makoto Це програма для пошуку пігаторових трійків. Квадратні корінці іноді можуть бути подвійними, але в той же час вони можуть бути іноді і міжрічними. Ви розумієте, що я маю на увазі?
JXPheonix

@JXPheonix: Значення можуть бути або значеннями з плаваючою комою, або цілим числом. Має сенс.
Макото

Відповіді:


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

Це перевіряє, чи є закруглене значення подвійного значення таким, як подвійне.

Ваша змінна може мати ціле або подвійне значення і Math.floor(variable)завжди має значення int, тому якщо ваша змінна дорівнює, Math.floor(variable)то вона повинна мати значення int.

Це також не працює, якщо значення змінної є нескінченним або негативним нескінченним, отже, додаючи умові "до тих пір, поки змінна не є нескінченною".


3
"Якщо аргументом є NaN або нескінченний чи позитивний нуль або від'ємний нуль, то результат такий же, як аргумент." docs.oracle.com/javase/6/docs/api/java/lang/…
Тім

2
@TimSchmelter: хороший улов. Варто також зазначити, що NaN не є рівним нічого (включаючи себе), але +/- Inf дорівнює самому собі - тому є два крайні випадки!
maerics

І Скон, і Фуад опублікували набагато кращі відповіді.
Джоель Крістофель

@JoelChristophel: Я не згоден. Це хороший спосіб, оскільки він виключає ризик переповнення типу. Єдине, що мені не сподобалося, було твердження про те, що змінна - це, intякщо ifоцінювачі true.
Вірсавія

@Bathsheba (Double.POSITIVE_INFINITY% 1) == 0 і його негативний аналог оцінюють як хибне.
Джоель Крістофель

222

Або ви можете скористатися оператором модуля:

(d % 1) == 0


2
Я дуже люблю простоту цього рішення. Це одночасно легко читати та реалізовувати.
krispy

1
Дуже інтуїтивне рішення
Даніель Сан

3
Що стосується обчислень, чи швидше, ніж Math.rint(d)?
iTurki

2
Так, це приємно, але зауважте, що це рішення Java і недостатньо чітко визначено для негативу dв C та C ++.
Вірсавія

4
У Sonar це створює проблему "Тести рівності не повинні проводитися зі значеннями з плаваючою комою".
Джуліо Д

86

Гуава : DoubleMath.isMathematicalInteger. (Розкриття: я написав це.) Або, якщо ви ще не імпортуєте Guava, x == Math.rint(x)це найшвидший спосіб зробити це; rintпомірно швидше ніж floorабо ceil.


3
Не знав про Math.rint Ви маєте рацію. Це набагато швидше, ніж Math.floor
Ленні Маркус

Це якось краще для прикладу кастингу Eng.Fouad?
Джоель Крістофель

@JoelChristophel: Так. Не всі парні з цілими значеннями знаходяться в діапазоні int або навіть довгих, так що тест не буде працювати на них.
Луї Вассерман

Готча. Тоді (d% 1) == 0 все ще діє.
Джоель Крістофель


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();

3

Поміркуйте:

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

Це дотримується основної Java і дозволяє уникнути порівняння рівності між значеннями плаваючої точки ( ==), що пропускається погано. isFinite()Необхідно , як rint()буде наскрізними значень нескінченності.



3

Ось хороше рішення:

if (variable == (int)variable) {
    //logic
}

чому (bool)акторський склад ?
xdavidliu

1
@xdavidliu Не потрібно в цьому. Ми можемо проігнорувати це.
Нітіш

2

Схожа на відповідь SkonJeet вище, але продуктивність краща (принаймні у java):

Double zero = 0d;    
zero.longValue() == zero.doubleValue()

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);
}

Більш правильна реалізація поверне помилкову, і вам доведеться написати інший метод, який приймає int як аргумент і повертає true. : D
альфа

0

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

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 d значення 33.15, метод повертає true. Для кращих результатів ви можете призначити менші значення для testRange (як 0,0002) на свій розсуд.


0

Особисто я віддаю перевагу простому модульному рішенню в прийнятій відповіді. На жаль, SonarQube не любить тести рівності з плаваючими точками без встановлення круглої точності. Тож ми спробували знайти більш сумісне рішення. Ось:

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

Remainder(BigDecimal)повертає BigDecimalзначення, значення якого (this % divisor). Якщо цей дорівнює нулю, ми знаємо, що немає плаваючої точки.



Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.