Cara menguji apakah dobel adalah bilangan bulat

166

Apakah mungkin melakukan ini?

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
}

Aku tahu kode mungkin tidak pergi sesuatu seperti itu, tapi bagaimana tidak pergi?

JXPheonix
sumber
1
C # tetapi serupa di Jawa: stackoverflow.com/a/4077262/284240 ( Integer.MAX_VALUE )
Tim Schmelter
1
Apa yang akan Anda dapatkan dari ini? doubledan intdiwakili dalam memori secara berbeda, dan Anda akan menggunakan satu atau yang lain berdasarkan konteks penanganan memori Anda.
Makoto
@ Legenda, saya akan melakukan hal yang sama seperti yang Anda sarankan; apakah Anda secara kebetulan tahu bagaimana% 1 membandingkan efisiensi-bijaksana dengan Math.floor (variabel) yang disarankan pengguna lain?
G. Bach
3
@ Makoto Ini adalah program untuk menemukan tripel pygatorean. Akar kuadrat kadang-kadang bisa dua kali lipat, tetapi pada saat yang sama mereka juga kadang-kadang bisa menjadi penyela. Anda mengerti maksud saya?
JXPheonix
@JXPheonix: Jadi nilai bisa berupa nilai titik-mengambang atau nilai integer. Masuk akal.
Makoto

Jawaban:

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

Ini memeriksa apakah nilai bulat dari ganda sama dengan ganda.

Variabel Anda bisa memiliki nilai int atau dobel dan Math.floor(variable)selalu memiliki nilai int, jadi jika variabel Anda sama denganMath.floor(variable) maka harus memiliki nilai int.

Ini juga tidak berfungsi jika nilai variabel tidak terbatas atau negatif tak terbatas maka menambahkan 'selama variabel tidak tidak terbatas' dengan kondisi.

maxhud
sumber
3
"Jika argumennya adalah NaN atau infinity atau nol positif atau negatif nol, maka hasilnya sama dengan argumen." docs.oracle.com/javase/6/docs/api/java/lang/…
Tim
2
@TimSchmelter: tangkapan bagus. Perlu juga dicatat bahwa NaN tidak sama dengan apa pun (termasuk dirinya sendiri) tetapi +/- Inf sama dengan dirinya sendiri - jadi ada dua case edge!
maerics
Baik Skon dan Fouad memposting jawaban yang jauh lebih baik.
Joel Christophel
@ JoelChristophel: Saya tidak setuju. Ini adalah cara yang baik karena menghilangkan risiko tipe overflow. Satu-satunya hal yang saya tidak suka adalah pernyataan bahwa variabel adalah intjika ifdievaluasi true.
Batsyeba
@Bathsheba (Gandakan.POSITIVE_INFINITY% 1) == 0 dan pasangan negatifnya sama-sama bernilai false.
Joel Christophel
223

Atau Anda dapat menggunakan operator modulo:

(d % 1) == 0

SkonJeet
sumber
2
Saya sangat menyukai kesederhanaan solusi ini. Keduanya mudah dibaca dan diimplementasikan.
krispy
1
Solusi yang sangat intuitif
Daniel San
3
Dalam hal perhitungan, apakah lebih cepat dari itu Math.rint(d)?
iTurki
2
Ya ini bagus, tetapi perhatikan juga ini adalah solusi Java dan tidak didefinisikan dengan baik untuk negatif ddalam C dan C ++.
Batsyeba
4
Di Sonar, ini menghasilkan masalah "Tes kesetaraan tidak boleh dilakukan dengan nilai floating point."
Julio D
86

Jambu: DoubleMath.isMathematicalInteger. (Pengungkapan: Saya menulisnya.) Atau, jika Anda belum mengimpor Jambu, x == Math.rint(x)adalah cara tercepat untuk melakukannya; rintsecara terukur lebih cepat dari flooratau ceil.

Louis Wasserman
sumber
3
Tidak tahu tentang Math.rint Anda benar. Ini jauh lebih cepat daripada Math.floor
Lenny Markus
Apakah ini entah bagaimana lebih disukai daripada contoh casting Eng.Fouad?
Joel Christophel
@ JoelChristophel: Ya. Tidak semua dobel dengan nilai integer berada dalam kisaran int, atau bahkan panjang, sehingga pengujian tidak akan berhasil.
Louis Wasserman
Kena kau. Kemudian (d% 1) == 0 masih valid.
Joel Christophel
20
public static boolean isInt(double d)
{
    return d == (int) d;
}
Eng.Fouad
sumber
6

Coba dengan cara ini,

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

sebagai contoh:

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

maka 12,9 adalah tidak integer, namun

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

karenanya 12.0 adalah integer

Sheldon
sumber
3

Ini versi untuk Integerdan 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;
    }
}

Untuk mengkonversi Doubleke Integer:

Integer intVariable = variable.intValue();
irudyak
sumber
3

Mempertimbangkan:

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

Ini menempel pada Java inti dan menghindari perbandingan kesetaraan antara nilai floating point ( ==) yang dianggap buruk. The isFinite()diperlukan karena rint()akan pass-through nilai tak terhingga.

simon.watts
sumber
3

Cara terbaik adalah dengan operator modulus

if(val % 1 == 0)
Abdul Hafeez Khan
sumber
1
dapatkah Anda menambahkan lebih banyak penjelasan untuk dijawab? Terima kasih!
Shanteshwar Inde
3

Ini solusi yang bagus:

if (variable == (int)variable) {
    //logic
}
Nitish
sumber
mengapa para (bool)pemain?
xdavidliu
1
@xdavidliu Tidak perlu untuk itu. Kita bisa mengabaikannya.
Nitish
2

Mirip dengan jawaban SkonJeet di atas, tetapi kinerjanya lebih baik (setidaknya dalam java):

Double zero = 0d;    
zero.longValue() == zero.doubleValue()
edwardsayer
sumber
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
sumber
Implementasi yang lebih benar akan menghasilkan false dan Anda harus menulis metode lain yang menjadikan int sebagai argumen dan mengembalikan true. : D
alfa
0

Anda bisa mencoba dengan cara ini: dapatkan nilai integer dari double, kurangi ini dari nilai double asli, tentukan rentang pembulatan dan uji apakah angka absolut dari nilai ganda baru (tanpa bagian integer) lebih besar atau lebih kecil dari Anda rentang yang ditentukan. jika lebih kecil, Anda bisa bermaksud itu adalah nilai integer. Contoh:

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

Jika Anda menetapkan ke d nilai 33,15 metode mengembalikan true. Untuk mendapatkan hasil yang lebih baik, Anda dapat menetapkan nilai yang lebih rendah ke testRange (0,0002) sesuai kebijakan Anda.

Salvi94
sumber
0

Secara pribadi, saya lebih suka solusi operasi modulo sederhana dalam jawaban yang diterima. Sayangnya, SonarQube tidak menyukai tes kesetaraan dengan floating point tanpa menetapkan presisi bulat. Jadi kami telah mencoba menemukan solusi yang lebih sesuai. Ini dia:

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

Remainder(BigDecimal)mengembalikan BigDecimalnilai yang (this % divisor). Jika yang ini sama dengan nol, kita tahu tidak ada floating point.

chaeschuechli
sumber
0

Solusi sederhana saya:

private boolean checkIfInt(double 
 value){
 return value - Math.floor(value) == 0;
 }
Mostafa Amer
sumber
-1

Inilah solusinya:

float var = Your_Value;
if ((var - Math.floor(var)) == 0.0f)
{
    // var is an integer, so do stuff
}
MOHIT GUPTA
sumber