ฉันจะตรวจสอบได้อย่างไรว่าตัวเลขมีค่าเป็นอินฟินิตี้หรือไม่


97

ฉันมีชุดการคำนวณ Javascript ที่ (เฉพาะใน IE) แสดง Infinity ขึ้นอยู่กับตัวเลือกของผู้ใช้

หนึ่งจะหยุดคำที่Infinityปรากฏและตัวอย่างเช่นแสดง0.0แทนได้อย่างไร

คำตอบ:


179
if (result == Number.POSITIVE_INFINITY || result == Number.NEGATIVE_INFINITY)
{
    // ...
}

คุณอาจใช้isFiniteฟังก์ชันนี้แทนได้ขึ้นอยู่กับว่าคุณต้องการรักษาNaNอย่างไร isFiniteผลตอบแทนfalseถ้าจำนวนของคุณPOSITIVE_INFINITY, หรือNEGATIVE_INFINITYNaN

if (isFinite(result))
{
    // ...
}

2
ทำไมต้องใช้Number.(POSITIVE|NEGATIVE)_INFINITYแทน-?Infinityหรือ-?1/0?
Eli Gray

5
@Eli: ทั่วโลกInfinityคุณสมบัติไม่ได้อ่านอย่างเดียวซึ่งหมายความว่ามันสามารถนิยามใหม่: ตัวอย่างเช่นvar x = 42; Infinity = 42; alert(x === Infinity);การแสดง"ความจริง" (เป็นที่ยอมรับว่าเป็นกรณีที่ชัดเจนและทุกคนที่ตัดสินใจที่จะ redefine Infinity, NaNฯลฯ ควรคาดหวังสิ่งที่แปลกที่เกิดขึ้น.)
LukeH

โดยไม่สนใจข้อเท็จจริงที่Number.(POSITIVE|NEGATIVE)_INFINITYไม่ใช่แบบอ่านอย่างเดียวInfinity คืออ่านอย่างเดียวในโหมดเข้มงวด แล้ว-?1/0กรณีที่ฉันนำเสนอให้คุณล่ะ? อย่างไรก็ตามคุณควรใช้isFiniteแทนกันเกือบตลอดเวลา
Eli Gray

1
@Eli: ในการทดสอบของฉันNumber.POSITIVE_INFINITYและNumber.NEGATIVE_INFINITY เป็นแบบอ่านอย่างเดียว (ทดสอบบน Chrome8, FF3.6 และ IE8) การใช้1/0งานได้ผลดี แต่จะไม่ชัดเจนนักสำหรับผู้ดูแลโค้ดของคุณว่าคุณกำลังพยายามทดสอบอะไรอยู่ ฉันยอมรับว่าการใช้isFiniteมักจะเป็นวิธีที่ดีกว่าในการทำสิ่งต่างๆนั่นคือเหตุผลที่ฉันพูดถึงในคำตอบของฉัน - แต่มีเพียง OP เท่านั้นที่สามารถตัดสินใจได้ว่าตรงตามข้อกำหนดของพวกเขาหรือไม่
LukeH

4
พวกเขาไม่ได้อ่านอย่างเดียว (อ่าน: ไม่สามารถกำหนดค่าได้ ) เป็นเพียงตัวเข้าถึงที่มี getters แต่ไม่มีตัวตั้งค่า คุณสามารถ redefine พวกเขาด้วยและObject.defineProperty บนมืออื่น ๆ ที่เป็นที่ไม่ใช่การกำหนดค่าในโหมดที่เข้มงวด __defineGetter__Infinity
Eli Gray

9

ง่ายn === n+1หรือใช้n === n/0งานได้:

function isInfinite(n) {
  return n === n/0;
}

โปรดทราบว่าเนทีฟisFinite()บีบบังคับอินพุตเป็นตัวเลข isFinite([])และisFinite(null)เป็นทั้งtrueตัวอย่าง


คำตอบนี้ผิดธรรมดา n === n+1ประเมินเป็นจริงสำหรับตัวเลขทั้งหมดที่มีขนาดใหญ่กว่า 2 ^ 53 เช่น 1e30 แฮ็คการแบ่งใช้งานได้แม้กระทั่งสำหรับ NaN และ -Infinity อย่างไรก็ตามคำตอบของ LukeH ช่วยให้คุณอ่านโค้ดได้ง่ายขึ้น
tglas

@tglas ทำไมบวกแบบนั้น? ดีใจที่กองมีความมั่นคง IMO รหัสของฉันอ่านได้ง่ายขึ้นและครอบคลุมมากขึ้นเนื่องจากคณิตศาสตร์เป็นสากลมากกว่าคำ
ryanve

1
เนื่องจากการลอยตัวของ IEEE 64 บิตมีเลขฐานสองที่มีนัยสำคัญ 53 หลัก (ดูที่en.wikipedia.org/wiki/IEEE_754 ) จึงn+1ไม่สามารถแสดงได้และอาจมีการปัดเศษ แม้แต่จำนวนเต็มก็ได้รับผลกระทบจากข้อผิดพลาดในการปัดเศษ Btw ฉันไม่คิดว่ารหัสของคุณคือ "คณิตศาสตร์หลักฐาน" n === n/-0เพียงแค่พยายาม เมื่อเติมจำนวนจริงด้วย +/- inf ขีด จำกัด ของคุณจะไม่ถูกกำหนดไว้อย่างชัดเจนเว้นแต่ว่าลำดับศูนย์ที่อยู่ภายใต้จะถือว่าเป็นค่าบวก
tglas

ขอบคุณ @tglas ฉันจะรักเสมอที่ JavaScript หารด้วยศูนย์ :)
ryanve


2

จริงๆแล้ว n === n + 1 จะใช้ได้กับตัวเลขที่ใหญ่กว่า 51 บิตเช่น

1e16 + 1 === 1e16; // true
1e16 === Infinity; // false

3
นี่ควรเป็นความคิดเห็นเกี่ยวกับคำตอบของ ryanve
Gary

1

ผมชอบที่จะใช้Lodashสำหรับความหลากหลายของการเข้ารหัสป้องกันเหตุผลเช่นเดียวกับการอ่าน ES6 Number.isFiniteดีมากและไม่มีปัญหากับค่าที่ไม่ใช่ตัวเลข แต่ถ้า ES6 ไม่สามารถทำได้แสดงว่าคุณมี lodash อยู่แล้วหรือต้องการรหัส briefer: _.isFinite

_.isFinite(Infinity); // false
_.isFinite(NaN); // false
_.isFinite(-Infinity); // false

_.isFinite(null); // false
_.isFinite(3); // true
_.isFinite('3'); // true

0

ฉันพบสถานการณ์ที่ทำให้ฉันต้องตรวจสอบว่าค่าเป็นNaNหรือInfinityประเภท แต่ส่งสตริงเป็นผลลัพธ์ที่ถูกต้อง เนื่องจากสตริงข้อความจำนวนมากจะสร้างผลบวกที่ผิดพลาดNaNฉันได้ทำวิธีง่ายๆเพื่อหลีกเลี่ยงสิ่งนั้น:

  const testInput = input => input + "" === "NaN" || input + "" === "Infinity";

โค้ดด้านบนจะแปลงค่าเป็นสตริงและตรวจสอบว่ามีค่าเท่ากับ NaN หรือ Infinity อย่างเคร่งครัดหรือไม่ (คุณจะต้องเพิ่มกรณีอื่นสำหรับค่าอินฟินิตี้เชิงลบ)

ดังนั้น:

testInput(1/0); // true
testInput(parseInt("String")); // true
testInput("String"); // false

โพสต์นี้ไม่ได้เกี่ยวข้องกับคำถามจริงที่นี่และน่าจะดีกว่าเมื่อแสดงความคิดเห็นภายใต้คำตอบที่ยอมรับ OP เป็นเรื่องของตัวเลขและอินฟินิตี้ไม่ใช่สตริงและNaNs ฯลฯ
code_dredd

คุณน่าจะใช่ @code_dredd - เกร็ดเล็กเกร็ดน้อยไม่เกี่ยวข้อง แต่วิธีแก้ปัญหายังคงใช้งานได้: สามารถตรวจจับหมายเลขอินฟินิตี้ได้ - โปรดแก้ไขฉันหากฉันผิด
dmitrizzle

ที่อยู่ข้างประเด็น มีคำตอบที่แสดงวิธีการทำอย่างถูกต้องอยู่แล้ว สิ่งที่คุณ "ใช้ได้ผล" เพียงเพราะตัวภาษาทำสิ่งที่ไร้สาระและไม่สอดคล้องกับวิธีจัดการประเภทต่างๆ โปรดช่วยตัวเองจากการเขียนรหัสแฮ็กเช่นนี้
code_dredd

จะทำให้คุณมีความสุขมากขึ้นไหมถ้าฉันใช้toString()แทน อย่าลังเลที่จะลงคะแนนหรือระบุเหตุผลที่อาจให้ผลลัพธ์ที่ไม่สอดคล้องกันได้อย่างไรหรือเหตุใดจึงไม่แนะนำให้ใช้วิธีนี้ จนถึงตอนนี้ฉันยังรู้สึกว่ามันเพิ่มตัวเลือกสำหรับใครก็ตามที่กำลังมองหาคำตอบและไม่มีเหตุผลที่เป็นรูปธรรมว่าทำไมสิ่งนี้ถึงอันตรายไม่เสถียร ฯลฯ
dmitrizzle

-1

คุณสามารถใช้isFiniteในหน้าต่างisFinite(123):

คุณสามารถเขียนฟังก์ชันเช่น:

function isInfinite(num) {
 return !isFinite(num);
}

และใช้เช่น:

isInfinite(null); //false
isInfinite(1); //false
isInfinite(0); //false
isInfinite(0.00); //false
isInfinite(NaN); //true
isInfinite(-1.797693134862316E+308); //true
isInfinite(Infinity); //true
isInfinite(-Infinity); //true
isInfinite(+Infinity); //true
isInfinite(undefined); //true

คุณยังสามารถNumber.isFinitตรวจสอบว่าค่าเป็น Number ด้วยหรือไม่และมีความแม่นยำมากขึ้นสำหรับการตรวจสอบundefinedและnullอื่น ๆ

หรือคุณสามารถทำpolyfillได้ดังนี้:

Number.isFinite = Number.isFinite || function(value) {
  return typeof value === 'number' && isFinite(value);
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.