วิธีการทดสอบว่า 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
}

ฉันรู้รหัสอาจจะไม่ได้ไปอะไรอย่างนั้น แต่วิธีการไม่ให้มันไป?


1
C # แต่คล้ายกันใน Java: stackoverflow.com/a/4077262/284240 ( Integer.MAX_VALUE )
Tim Schmelter

1
คุณจะได้อะไรจากสิ่งนี้ doubleและintจะแสดงในหน่วยความจำแตกต่างกันและคุณจะใช้อย่างใดอย่างหนึ่งขึ้นอยู่กับบริบทของการจัดการหน่วยความจำของคุณ
Makoto

@ ตำนานฉันจะทำเช่นเดียวกับที่คุณแนะนำ; คุณโดยบังเอิญรู้หรือไม่ว่า% 1 เปรียบเทียบประสิทธิภาพอย่างชาญฉลาดกับ Math.floor (ตัวแปร) ที่ผู้ใช้รายอื่นแนะนำอย่างไร
G. Bach

3
@Makoto มันเป็นโปรแกรมสำหรับค้นหา pygatorean triples รากที่สองสามารถบางครั้ง แต่ในเวลาเดียวกันพวกเขาก็สามารถ intergers คุณได้รับสิ่งที่ฉันหมายถึงอะไร
JXPheonix

@JXPheonix: ดังนั้นค่าอาจเป็นค่าทศนิยมหรือค่าจำนวนเต็ม มีเหตุผล.
Makoto

คำตอบ:


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

สิ่งนี้จะตรวจสอบว่าค่าที่ปัดเศษลงของ double นั้นเหมือนกันกับ double หรือไม่

ตัวแปรของคุณอาจมีค่า int หรือ double และMath.floor(variable)มีค่า int เสมอดังนั้นหากตัวแปรของคุณเท่ากับMath.floor(variable)มันต้องมีค่า int

สิ่งนี้ยังใช้งานไม่ได้ถ้าค่าของตัวแปรไม่มีที่สิ้นสุดหรือลบไม่ จำกัด ดังนั้นการเพิ่ม 'ตราบใดที่ตัวแปรไม่ได้อยู่ในเงื่อนไข'


3
"ถ้าอาร์กิวเมนต์เป็น NaN หรืออินฟินิตี้หรือศูนย์บวกหรือศูนย์ลบผลลัพธ์จะเหมือนกับอาร์กิวเมนต์" docs.oracle.com/javase/6/docs/api/java/lang/…
Tim Schmelter

2
@TimSchmelter: จับได้ดี นอกจากนี้ยังเป็นที่น่าสังเกตว่า NaN ไม่เท่ากัน (รวมถึงตัวเอง) แต่ +/- Inf เท่ากับตัวเอง - ดังนั้นจึงมีสองกรณีที่เป็นขอบ!
maerics

ทั้ง Skon และ Fouad โพสต์คำตอบที่ดีกว่ามาก
Joel Christophel

@JoelChristophel: ฉันไม่เห็นด้วย นี่เป็นวิธีที่ดีเพราะจะช่วยลดความเสี่ยงในการพิมพ์ล้น สิ่งเดียวที่ฉันไม่ชอบก็ยืนยันว่าตัวแปรเป็นintถ้าประเมินif true
Bathsheba

@Bathsheba (Double.POSITIVE_INFINITY% 1) == 0 และค่าลบทั้งคู่ประเมินว่าเป็นเท็จ
Joel Christophel

223

หรือคุณสามารถใช้ตัวดำเนินการโมดูโล:

(d % 1) == 0


2
ฉันชอบความเรียบง่ายของโซลูชันนี้จริงๆ ง่ายต่อการอ่านและนำไปใช้
krispy

1
โซลูชันที่ใช้งานง่ายมาก
Daniel San

3
ในแง่ของการคำนวณมันเร็วกว่าMath.rint(d)ไหม?
iTurki

2
ใช่นี่เป็นสิ่งที่ดี แต่โปรดทราบว่านี่เป็นวิธีแก้ปัญหาของ Java และไม่ได้กำหนดอย่างชัดเจนสำหรับเชิงลบdใน C และ C ++
Bathsheba

4
ใน Sonar สิ่งนี้จะสร้างปัญหา "การทดสอบความเท่าเทียมกันไม่ควรทำด้วยค่าจุดลอยตัว"
Julio D

86

ฝรั่ง: DoubleMath.isMathematicalInteger. (การเปิดเผยข้อมูล: ฉันเขียนไว้) หรือถ้าคุณยังไม่ได้นำเข้า Guava x == Math.rint(x)เป็นวิธีที่เร็วที่สุดที่จะทำ rintเป็นวัดได้เร็วกว่าหรือfloorceil


3
ไม่ทราบเกี่ยวกับ Math.rint คุณถูกต้อง มันเร็วกว่า Math.floor
Lenny Markus

นี่เป็นตัวอย่างที่ดีกว่าของ Eng.Fouad หรือเปล่า?
Joel Christophel

@JoelChristophel: ใช่ ไม่ใช่คู่ทั้งหมดที่มีค่าจำนวนเต็มอยู่ในช่วงของ int หรือแม้กระทั่งนานดังนั้นการทดสอบจะไม่ทำงานกับพวกเขา
Louis Wasserman

Gotcha จากนั้น (d% 1) == 0 ยังคงใช้ได้
Joel Christophel


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(val % 1 == 0)

1
คุณช่วยเพิ่มคำอธิบายเพิ่มเติมเพื่อตอบคำถามได้ไหม? ขอบคุณ!
Shanteshwar Inde

3

นี่คือทางออกที่ดี:

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

ทำไมถึง(bool)เลือกนักแสดง
xdavidliu

1
@xdavidliu ไม่จำเป็นสำหรับสิ่งนั้น เราสามารถเพิกเฉยได้
Nitish

2

คล้ายกับคำตอบของ SkonJeet ด้านบน แต่ประสิทธิภาพดีกว่า (อย่างน้อยในภาษาจาวา):

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 เป็นอาร์กิวเมนต์และส่งกลับจริง : D
alfa

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

หากคุณกำหนดให้กับค่า 33.15 เมธอดจะส่งกลับค่าจริง เพื่อให้ได้ผลลัพธ์ที่ดีขึ้นคุณสามารถกำหนดค่าที่ต่ำกว่าให้กับ 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)ถ้าอันนี้เท่ากับศูนย์เรารู้ว่าไม่มีจุดลอยตัว



โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.