2 คะแนน โดย GN⁺ 12 일 전 | 1 ความคิดเห็น | แชร์ทาง WhatsApp
  • รับอินพุตเป็น สหภาพของช่วงที่แยกจากกัน แล้วคำนวณได้ทั้งสี่การดำเนินการพื้นฐาน การเรียกฟังก์ชัน และการยกกำลัง โดยสามารถคำนวณ interval union arithmetic ได้โดยตรงในเบราว์เซอร์
  • ช่วงผลลัพธ์จะต้อง ครอบคลุม ค่าที่ได้จากการเลือกค่าจากสหภาพอินพุตแล้วคำนวณนิพจน์เดียวกันบนจำนวนจริงเสมอ และยังรองรับ การหารด้วยช่วงที่มี 0 อยู่ภายใน ในรูปแบบสหภาพที่แยกจากกันได้
  • ใน 1 / [-2, 1] จะได้ [-∞, -0.5] U [1, +∞] และใน tan([pi/3, 2*pi/3]) จะได้ [-∞, -1.732] U [1.732, +∞] แสดงให้เห็นว่ารองรับทั้ง ผลลัพธ์เป็นช่วงไม่ต่อเนื่อง และ ขอบเขตแบบอนันต์
  • รองรับไวยากรณ์และฟังก์ชันที่หลากหลาย เช่น [a, b], [a, b] U [c, d], ไวยากรณ์ช่วงซ้อนกัน, lo, hi, hull, log10, cos, min, max
  • ใน โหมดความแม่นยำเต็มรูปแบบ จะคืนช่วงที่ครอบค่าจริงด้วยการปัดออกด้านนอกบนพื้นฐาน IEEE 754 double precision และจุดเด่นคือแสดง 0.1 + 0.2 เป็น [0.29999999999999993, 0.3000000000000001]

ภาพรวม

  • เป็นเครื่องคิดเลขที่คำนวณกับ สหภาพของช่วงที่แยกจากกัน และรองรับการทำงานของ interval union arithmetic นอกเหนือจากจำนวนจริงทั่วไป
    • ช่วง [a, b] หมายถึงจำนวนทั้งหมดตั้งแต่ a ถึง b และ [a, b] U [c, d] หมายถึงสหภาพของช่วงที่แยกห่างกัน
    • เป็นส่วนขยายของ interval arithmetic แบบทั่วไป และสามารถคำนวณ การหารด้วยช่วงที่มี 0 อยู่ภายใน โดยยังคงคุณสมบัติการปิดไว้ได้
  • รับประกันคุณสมบัติการครอบคลุม
    • หากเลือกจำนวนจริงใด ๆ อย่างละหนึ่งค่าจากสหภาพอินพุต แล้วคำนวณนิพจน์เดียวกันบนจำนวนจริง ผลลัพธ์นั้นจะถูกรวมอยู่ในสหภาพผลลัพธ์เสมอ
  • ใช้แสดงความไม่แน่นอนได้
    • มีตัวอย่างผลลัพธ์ของ 50 * (10 + [-1, 1]) เป็น [450, 550]
  • รองรับการคำนวณนิพจน์ช่วงที่ซับซ้อน
    • สามารถป้อนนิพจน์อย่าง ( [5, 10] U [15, 16] ) / [10, 100] โดยใช้ตัวดำเนินการ U
    • มีตัวอย่างผลลัพธ์เป็น [0.05, 1.6]
  • ผลลัพธ์ของการคำนวณอาจเป็นสหภาพที่แยกจากกันได้
    • 1 / [-2, 1] ให้ผลลัพธ์ [-∞, -0.5] U [1, +∞]
    • tan([pi/3, 2*pi/3]) ให้ผลลัพธ์ [-∞, -1.732] U [1.732, +∞]
  • ในโหมดความแม่นยำเต็มรูปแบบ สามารถใช้เหมือนเครื่องคิดเลขทั่วไปได้ พร้อมคืนผลลัพธ์แบบช่วงที่ครอบค่าจริงรวมถึง ปัญหาความแม่นยำของเลขทศนิยมลอยตัว
    • ยกตัวอย่าง 0.1 + 0.2 ให้ผลลัพธ์ [0.29999999999999993, 0.3000000000000001]

ไวยากรณ์

  • รองรับรูปแบบพื้นฐาน
    • รองรับการเขียนช่วงแบบ [a, b]
    • ตัวอย่าง [0.5, 0.6]
  • รองรับการเขียนสหภาพ
    • รองรับรูปแบบ [a, b] U [c, d]
    • ตัวอย่าง [0, 1] U [5, 6]
  • รองรับสี่การดำเนินการพื้นฐานและการยกกำลัง
    • การบวก A + B ตัวอย่าง ➤ [90, 100] + [-2, 2] ผลลัพธ์ [88, 102]
    • การลบ A - B ตัวอย่าง ➤ [14, 16] - [8, 12] ผลลัพธ์ [2, 8]
    • การคูณ A * B ตัวอย่าง ➤ [-5, 10] * [2, 4] ผลลัพธ์ [-20, 40]
    • การหาร A / B ตัวอย่าง ➤ [2, 4] / [-1, 2] ผลลัพธ์ [-∞, -2] U [1, +∞]
    • การยกกำลัง A ^ B ตัวอย่าง ➤ [2, 3] ^ [-2, 3] ผลลัพธ์ [0.1111, 27]
  • รองรับฟังก์ชันและค่าคงที่
    • รองรับการเรียกฟังก์ชันในรูปแบบ function(...)
    • log10([1, 10000]) ให้ผลลัพธ์ [0, 4]
    • รองรับการป้อนชื่อค่าคงที่
    • pi ให้ผลลัพธ์ [3.1415926535897927, 3.1415926535897936]
  • ป้อนตัวเลขผสมกับช่วงได้
    • สามารถป้อนช่วงด้วยไวยากรณ์วงเล็บเหลี่ยมแบบ [1, 2]
    • ตัวเลขอย่าง 3.14 จะถูกตีความเป็นช่วงแคบความกว้าง 0 คือ [3.14, 3.14]
    • ในโหมดความแม่นยำเต็มรูปแบบ จะมีรายละเอียดที่แตกต่างกันในส่วนนี้
    • 1.55 + [-0.002, 0.002] ให้ผลลัพธ์ [1.548, 1.552]
  • รองรับไวยากรณ์ช่วงซ้อนกัน
    • สามารถป้อน [0, [0, 100]] และได้ผลลัพธ์ [0, 100]
    • แม้แต่ตัวเลขด้านในที่ใช้กำหนดขอบเขตช่วงก็จะถูกตีความเป็นช่วงด้วย
    • หากมีช่วงอยู่ในตำแหน่งขอบเขตของช่วงซ้อน จะใช้ค่าขอบบนของช่วงนั้น
    • การออกแบบนี้ทำให้สามารถใช้เลขคณิตกับตัวขอบเขตเองได้
    • [0, cos(2*pi)] ให้ผลลัพธ์ [0, 1]

ฟังก์ชันที่รองรับ

  • รองรับค่าคงที่
    • รองรับ inf, , pi, e
    • [-inf, 0] * [-inf, 0] ให้ผลลัพธ์ [0, +∞]
  • รองรับฟังก์ชันดึงขอบเขต
    • lo(A) คืนค่าขอบล่าง
      • lo([1, 2]) ให้ผลลัพธ์ [1, 1]
    • hi(A) คืนค่าขอบบน
      • hi([1, 2]) ให้ผลลัพธ์ [2, 2]
  • รองรับการคำนวณเปลือกช่วง
    • hull(A) จะครอบสหภาพให้เป็นช่วงเดียว
    • hull([1, 2] U [99, 100]) ให้ผลลัพธ์ [1, 100]
  • รองรับฟังก์ชันคณิตศาสตร์พื้นฐาน
    • abs(A) ตัวอย่าง abs([-10, 5]) ให้ผลลัพธ์ [0, 10]
    • sqrt(A) ตัวอย่าง sqrt([9, 49]) ให้ผลลัพธ์ [3, 7]
    • sqinv(A) ตัวอย่าง sqinv([4, 64]) ให้ผลลัพธ์ [-8, -2] U [2, 8]
  • รองรับฟังก์ชันลอการิทึมและเอกซ์โพเนนเชียล
    • log(A) ตัวอย่าง log([0, 1]) ให้ผลลัพธ์ [-∞, 0]
    • log2(A) ตัวอย่าง log2([64, 1024]) ให้ผลลัพธ์ [6, 10]
    • log10(A) ตัวอย่าง log10([0.0001, 1]) ให้ผลลัพธ์ [-4, 0]
    • exp(A) ตัวอย่าง exp([-∞, 0] U [1, 2]) ให้ผลลัพธ์ [0, 1] U [2.718, 7.389]
  • รองรับฟังก์ชันตรีโกณมิติและตรีโกณมิติผกผัน
    • cos(A) ตัวอย่าง cos([pi/3, pi]) ให้ผลลัพธ์ [-1, 0.5]
    • sin(A) ตัวอย่าง sin([pi/6, 5*pi/6]) ให้ผลลัพธ์ [0.5, 1]
    • tan(A) ตัวอย่าง tan([pi/3, 2*pi/3]) ให้ผลลัพธ์ [-∞, -1.732] U [1.732, +∞]
    • acos(A) ตัวอย่าง acos([-1/2, 1/2]) ให้ผลลัพธ์ [1.047, 2.094]
    • asin(A) ตัวอย่าง asin([0, 1]) ให้ผลลัพธ์ [0, 1.571]
    • atan(A) ตัวอย่าง atan([-10, 2]) ให้ผลลัพธ์ [-1.471, 1.107]
  • รองรับฟังก์ชันค่าน้อยสุดและค่ามากสุด
    • min(A, B) ตัวอย่าง min([1, 2], [0, 6]) ให้ผลลัพธ์ [0, 2]
    • max(A, B) ตัวอย่าง max([0, 10], [5, 6]) ให้ผลลัพธ์ [5, 10]

โหมดความแม่นยำเต็มรูปแบบ

  • ใช้การปัดออกด้านนอกบนเลขทศนิยมลอยตัวแบบ IEEE 754 double precision
    • ใช้ชนิด number ของ JavaScript
    • รับประกันว่าช่วงผลลัพธ์จะครอบค่าจริงที่ได้เมื่อคำนวณนิพจน์เดียวกันบนจำนวนจริงด้วยความแม่นยำไม่จำกัดเสมอ
  • มีตัวอย่างกรณี 0.1 + 0.2
    • 0.3 ไม่สามารถแทนได้อย่างแม่นยำในเลขทศนิยมลอยตัวแบบ double precision
    • interval arithmetic จะคำนวณช่วงที่ครอบ 0.3 ไว้
  • การทำงานเมื่อเปิดโหมดความแม่นยำเต็มรูปแบบ
    • ตัวเลขที่ผู้ใช้ป้อนจะถูกตีความเป็น ช่วงที่เล็กที่สุด ซึ่งครอบค่า IEEE 754 ที่ใกล้กับเลขฐานสิบที่ป้อนมากที่สุด โดยขอบทั้งสองด้านไม่เท่ากับค่านั้น
    • ตัวเลขผลลัพธ์จะแสดงด้วยเลขฐานสิบทุกหลักที่สามารถใช้ได้
    • ใช้ Number.toString()
  • การทำงานเมื่อปิดโหมดความแม่นยำเต็มรูปแบบ
    • ตัวเลขที่ผู้ใช้ป้อนจะถูกตีความเป็น ช่วงเสื่อม ที่มีขอบทั้งสองด้านเท่ากับค่า IEEE 754 ที่ใกล้กับเลขฐานสิบที่ป้อนมากที่สุด
    • ตัวเลขผลลัพธ์จะแสดงทศนิยมได้สูงสุด 4 ตำแหน่ง
    • ใช้ Number.toPrecision()

บั๊ก

  • มีการระบุว่าเครื่องคิดเลขอาจยังมีบั๊กหลงเหลืออยู่
  • มีลิงก์ GitHub Issues สำหรับรายงานปัญหา

โอเพนซอร์ส

  • ทั้ง Interval Calculator และเอนจินคำนวณ not-so-float เปิดเป็นโอเพนซอร์ส
  • มีลิงก์สนับสนุนผ่าน GitHub Sponsors

งานในอนาคต

  • มีแผนจะแยกโหมดความแม่นยำเต็มรูปแบบออกเป็นตัวควบคุม 2 รายการ
    • การตีความอินพุต
    • ความละเอียดของการแสดงผล
  • มีแผนเพิ่มตัวแปร ans
    • ใช้เก็บผลลัพธ์จากอินพุตก่อนหน้า
  • มีแผนเพิ่มตัวดำเนินการหรือฟังก์ชันหาจุดตัด
  • มีแผนปรับปรุงความเป็นธรรมชาติของลำดับความสำคัญของตัวดำเนินการ U
  • มีแผนรองรับการป้อนสหภาพว่าง

1 ความคิดเห็น

 
GN⁺ 12 일 전
ความคิดเห็นจาก Hacker News
  • ในฐานะผู้เขียนเอง ขอพูดว่า การปัดออกด้านนอก เป็นสิ่งที่โด่งดังที่สุดใน interval arithmetic สำหรับรับมือปัญหาเรื่องความแม่นยำก็จริง แต่ผมเสียดายที่คนมักโฟกัสแค่นั้น คุณสมบัติ inclusion property ที่พูดถึงในงานวิจัยนั้นทำงานได้ในทุกสเกล จึงได้ผลลัพธ์อย่าง 50 * (10 + [-1, 1]) = [450, 550] อย่างเป็นธรรมชาติ และพอซ้อนเลเยอร์ union เข้าไป ก็สามารถจัดการสิ่งอย่างฟังก์ชันผกผันที่แท้จริงของฟังก์ชันยกกำลังสองได้ด้วย ลองทำ sqinv(64) แทน sqrt แล้วจะเห็นภาพ จริง ๆ แล้ว interval calculator นี้ทำขึ้นเพื่อทดสอบ implementation ของ interval union arithmetic ที่กำลังสร้างไว้สำหรับอีกโปรเจ็กต์หนึ่งคือ backwards updating spreadsheet ตัว implementation อยู่ที่ not-so-float และโปรเจ็กต์ที่เกี่ยวข้องมี bidicalc กับ วงสนทนา HN
    • อยากรู้ว่า arithmetic ที่คุณ implement แตกต่างจากมาตรฐาน IEEE 1788 อย่างไรบ้าง และสองเปเปอร์ที่ลิงก์ไว้นั้นเกี่ยวข้องกับมาตรฐานนั้นอย่างไรด้วย อยากรู้ว่าถ้าจะแก้ปัญหาที่บทความพูดถึง จำเป็นต้องเริ่มใหม่ทั้งหมดหรือว่าสามารถต่อยอดบนมาตรฐาน IEEE ได้
    • เจ๋งมากจนคิดว่าจะลองเล่นต่ออีกหน่อย มีสองอย่างที่สงสัยเป็นพิเศษ อย่างแรกคือการเพิ่ม ฟังก์ชันหลายค่า จะยากแค่ไหน เช่น ถ้าทำ asin(1) แล้วได้เซตทั้งหมด [pi/2, pi/2] + n[2pi, 2pi] โดยไม่ต้องพึ่ง Mathematica คงดีมาก อย่างที่สองคือข้อความอธิบายการตีความตัวเลขที่ผู้ใช้ป้อนค่อนข้างชวนสับสน สำหรับผม ดูเหมือนว่าค่า ขอบเขตผลลัพธ์ ของช่วงที่เล็กที่สุดซึ่งครอบค่าที่ป้อน ควรเป็นเลข IEEE 754 สองค่าที่ใกล้ที่สุดซึ่งประกบค่าที่ป้อนอยู่ แต่ข้อความปัจจุบันอ่านแล้วให้ความรู้สึกเหมือน IEEE754(input)+[-epsilon, epsilon] ซึ่งความหมายต่างออกไป
  • อันนี้ดีมาก งาน implicit surfaces ของ Matt Keeter และการ optimize ด้วย interval math ก็น่าสนใจมากเช่นกัน ดูได้จากการบรรยายนี้
  • ผมก็มี graphing calculator ที่ทำด้วย interval arithmetic เหมือนกัน น่าจะสนใจ ลองใช้ได้ที่ formulagraph และมีคำอธิบายการทำงานกับโค้ดที่เกี่ยวข้องอยู่ในบทความนี้
    • ความรู้สึกแรกคล้าย GrafEq มาก ทำให้นึกถึง GrafEq สมัยก่อน
  • ผมก็เคยลองเขียนไลบรารี Math::Interval เล็ก ๆ ใน Raku เพราะสนุกกับเรื่องนี้เหมือนกัน ชื่อ raku-Math-Interval เป็นการทดลองที่สร้างบน Junction และคลาส Range ที่มีในตัวของ Raku และเป็นประสบการณ์ที่น่าสนใจทีเดียว
  • ดีมาก และขอบคุณที่แชร์ ผมคิดว่าถ้าแสดงด้วยว่า interval นั้น รวมขอบบน·ขอบล่างหรือไม่ จะยิ่งดี สัญลักษณ์ที่ผมคุ้นเคยคือใช้วงเล็บหันออกด้านนอกเมื่อไม่รวมค่านั้น และใช้แบบนั้นกับอนันต์เสมอ เช่น ]-∞, -1] U [0.5, +∞[ ส่วนช่วงที่ถูกตัดออกตรงกลางจะเป็น ]-1, 0.5[ เท่าที่ผมเข้าใจ min กับ max ก็น่าจะตีความในลักษณะนี้ด้วย และถ้ามี ไอเดียด้าน UI แบบคลิกหรือแตะสูตรในพื้นที่ผลลัพธ์เพื่อคัดลอกกลับไปช่องป้อน ก็น่าจะสะดวก
    • พออ่านเปเปอร์ที่ลิงก์แล้ว ที่นี่อธิบายเฉพาะ ช่วงปิด เท่านั้น interval union ถูกนิยามว่าเป็นเซตของช่วงที่ปิดและแยกจากกัน โดยมีเพียงขอบของ extreme interval ที่ปลายทั้งสองด้านเท่านั้นที่อาจเป็น ±∞ ได้
    • รองรับสัญลักษณ์แบบนั้นได้อยู่ แต่โค้ดจะ ซับซ้อนขึ้นมาก ดังนั้นเลยตัดสินใจตั้งแต่ช่วงแรกว่าจะไม่รองรับ ถึงอย่างนั้นมันก็อาจเป็นฟีเจอร์เสริมที่เท่มากได้
    • ผมก็งงตรงนี้นิดหน่อยเหมือนกัน สัญลักษณ์ มาตรฐาน ที่ผมรู้จักคือวงเล็บโค้ง แต่ก็คิดว่าในสภาพแวดล้อมแบบ ASCII มันอาจไม่ค่อยเหมาะ
  • สุดยอดมาก ผมไม่ได้เข้าใจทุก operation แบบสมบูรณ์ แต่เท่าที่เข้าใจก็น่าประทับใจมาก ทำให้นึกว่าถ้าได้เจอ เลขคณิตบนช่วง ตั้งแต่ตอนเรียนก็คงดี เพราะในสถิติพื้นฐานก็มีช่วงความเชื่อมั่น หรือในสมการกำลังสองก็มีเครื่องหมาย ± ซึ่งเป็นแนวคิดคล้ายกันอยู่แล้ว แต่เรากลับไม่ค่อยได้เอาผลลัพธ์นั้นมาคำนวณต่อเป็นข้อมูลก้อนเดียว มักต้องแยกจัดการสองค่าของ ± ทุกครั้ง แน่นอนว่าเข้าใจว่าครูคงอยากรีบไปสู่การประยุกต์ใช้เลยไม่ลงลึก แต่ก็น่าจะมีการบอกใบ้บ้างว่าแม้แต่กับวัตถุแบบนี้ก็ทำเลขคณิตทั่วไปได้ สิ่งที่คุณแสดงมานั้นไปไกลกว่านั้นมาก แต่ให้ความรู้สึกเหมือนเป็น การยืนยัน ว่ามุมมองที่เห็น interval เป็นข้อมูลที่มีพฤติกรรมของตัวเองนั้นสมเหตุสมผล
  • ผมคิดเหมือนกันว่า ถ้าตอนเริ่มใช้ไลบรารีช่วงเวลาชื่อ tick ใน Clojure ครั้งแรก ได้รู้จัก interval arithmetic ก่อนก็คงดี ไลบรารีนี้มี implementation ของ Allen's Interval Algebra อยู่ด้วย และยังรับเอาแนวคิดเรื่อง เซตของช่วงไม่ต่อเนื่อง ที่มีประโยชน์กับการคำนวณในงานจริง เช่น งาน HR ที่ต้องคำนวณเซตของช่วงวันลาภายในปีใดปีหนึ่ง ผมรู้จักงานของ Allen อยู่ประมาณนั้น แล้วก็บังเอิญค้นพบข้อดีของเซตแบบนี้เข้า โค้ดอยู่ที่ juxt/tick
  • ผมมองเห็นประโยชน์ของเครื่องมือนี้ชัดเจน แต่ส่วนตัวคิดว่า เครื่องคิดเลขเชิงความน่าจะเป็น อาจมีประโยชน์กว่า เช่น ผลของ 1 / [-1, 2] ไม่ได้บอกเลยว่าค่าไหนน่าจะเป็นไปได้มากน้อยแค่ไหน และแม้สมมติว่าอินพุตกระจายแบบสม่ำเสมอ เอาต์พุตก็ดูไม่น่าจะเป็น uniform distribution อย่างแน่นอน
  • ผมก็เพิ่ง implement อะไรคล้ายกันไป แต่ใช้มุมมองด้าน การเป็นสมาชิกของเซต ดังนั้นถ้าจะทำ Boolean analysis แบบสมบูรณ์กับ interval membership ก็จำเป็นต้องมี การดำเนินการ complement ช่วงในที่นี้ทั้งหมดเป็นเซตปิด ดังนั้น complement จึงกลายเป็นช่วงเปิด แต่ในกรณีใช้งานของผม ความต่างเรื่องรวมปลายหรือไม่รวมปลายไม่สำคัญ จึงไม่ได้แยกช่วงเปิดกับช่วงปิดออกจากกัน และยิ่งไปกว่านั้น ผมคิดว่าในเลขคณิตที่ไม่แม่นตรงนัก การที่เซตเป็นช่วงเปิดหรือปิดเองก็อาจนิยามได้ไม่ชัดด้วยซ้ำ
  • การขยายตรรกะไปเป็น union of intervals ดูเท่มาก แต่ผมสงสัยเรื่อง ความซับซ้อน ถ้า operation หนึ่งสามารถสร้างได้สองช่วง เมื่อทำ N operation ก็อาจเกิด การเติบโตแบบเอ็กซ์โปเนนเชียล ในบางกรณี แบบนั้นก็น่ากังวลว่าสำหรับงานใช้งานทั่วไปอย่าง abstract interpretation มันอาจไม่สมจริง เว้นแต่ว่าจะใส่การประมาณค่าเมื่อจำนวนช่วงเกินระดับหนึ่ง
    • เป็นข้อสังเกตที่ถูกต้อง และปัญหาแบบนี้ก็เป็นที่รู้จักกันดีในฝั่ง abstract interpretation อย่างที่คุณว่า ปกติจะตั้ง cap ให้ขนาดของออบเจ็กต์ แล้วถ้าเกินก็รวมช่วงเข้าด้วยกัน อย่างน้อยใน abstract interpretation เอง ก็ดูเหมือนว่าหลายครั้งจะใช้โดเมนที่ ละเอียดกว่า interval ด้วย