2 điểm bởi GN⁺ 5 ngày trước | 1 bình luận | Chia sẻ qua WhatsApp
  • Nhận đầu vào là hợp của các khoảng rời nhau, có thể thực hiện bốn phép toán cơ bản, gọi hàm và cả lũy thừa, đồng thời tính trực tiếp interval union arithmetic ngay trong trình duyệt
  • Khoảng kết quả chắc chắn chứa giá trị thu được khi chọn các giá trị từ hợp đầu vào rồi tính cùng biểu thức trên số thực, và ngay cả phép chia cho khoảng chứa 0 cũng có thể được xử lý dưới dạng hợp rời nhau
  • Với 1 / [-2, 1] cho ra [-∞, -0.5] U [1, +∞]tan([pi/3, 2*pi/3]) cho ra [-∞, -1.732] U [1.732, +∞], công cụ hỗ trợ biểu diễn kết quả là các khoảng gián đoạnbiên vô cực
  • Hỗ trợ nhiều cú pháp và hàm như [a, b], [a, b] U [c, d], cú pháp khoảng lồng nhau, lo, hi, hull, log10, cos, min, max
  • Trong chế độ toàn độ chính xác, công cụ trả về các khoảng bao chứa giá trị thực bằng cách làm tròn ra ngoài dựa trên IEEE 754 double precision; điểm nổi bật là hiển thị 0.1 + 0.2 thành [0.29999999999999993, 0.3000000000000001]

Tổng quan

  • Đây là máy tính tính toán trên hợp của các khoảng rời nhau, hỗ trợ triển khai interval union arithmetic chứ không chỉ số thực thông thường
    • Khoảng [a, b] nghĩa là toàn bộ các số từ a đến b, còn [a, b] U [c, d] là hợp của các khoảng tách rời nhau
    • Đây là dạng mở rộng của số học khoảng thông thường và cho phép tính cả phép chia cho khoảng chứa 0 mà vẫn giữ được tính đóng
  • Bảo đảm tính bao chứa
    • Nếu chọn ngẫu nhiên một số thực từ mỗi hợp đầu vào rồi tính cùng biểu thức trên số thực, kết quả đó chắc chắn sẽ nằm trong hợp đầu ra
  • Có thể biểu diễn độ bất định
    • Cung cấp ví dụ kết quả của 50 * (10 + [-1, 1])[450, 550]
  • Hỗ trợ tính các biểu thức khoảng phức tạp
    • Có thể nhập các biểu thức như ( [5, 10] U [15, 16] ) / [10, 100] bằng toán tử U
    • Cung cấp ví dụ kết quả là [0.05, 1.6]
  • Kết quả phép toán có thể là một hợp rời nhau
    • Kết quả của 1 / [-2, 1][-∞, -0.5] U [1, +∞]
    • Kết quả của tan([pi/3, 2*pi/3])[-∞, -1.732] U [1.732, +∞]
  • Ở chế độ toàn độ chính xác, công cụ có thể dùng như máy tính thông thường nhưng vẫn trả về các khoảng bao chứa giá trị thực, bao gồm cả vấn đề độ chính xác số dấu phẩy động
    • Ví dụ kết quả 0.1 + 0.2[0.29999999999999993, 0.3000000000000001]

Cú pháp

  • Hỗ trợ ký pháp cơ bản
    • Hỗ trợ ký pháp khoảng [a, b]
    • Ví dụ [0.5, 0.6]
  • Hỗ trợ ký pháp hợp
    • Hỗ trợ dạng [a, b] U [c, d]
    • Ví dụ [0, 1] U [5, 6]
  • Hỗ trợ bốn phép toán cơ bản và lũy thừa
    • Phép cộng A + B, ví dụ ➤ [90, 100] + [-2, 2] cho kết quả [88, 102]
    • Phép trừ A - B, ví dụ ➤ [14, 16] - [8, 12] cho kết quả [2, 8]
    • Phép nhân A * B, ví dụ ➤ [-5, 10] * [2, 4] cho kết quả [-20, 40]
    • Phép chia A / B, ví dụ ➤ [2, 4] / [-1, 2] cho kết quả [-∞, -2] U [1, +∞]
    • Lũy thừa A ^ B, ví dụ ➤ [2, 3] ^ [-2, 3] cho kết quả [0.1111, 27]
  • Hỗ trợ hàm và hằng số
    • Hỗ trợ gọi hàm theo dạng function(...)
    • log10([1, 10000]) cho kết quả [0, 4]
    • Hỗ trợ nhập tên hằng số
    • pi cho kết quả [3.1415926535897927, 3.1415926535897936]
  • Có thể trộn số và khoảng trong đầu vào
    • Có thể nhập khoảng bằng cú pháp ngoặc vuông như [1, 2]
    • Số như 3.14 được hiểu là khoảng hẹp có độ rộng 0: [3.14, 3.14]
    • Trong chế độ toàn độ chính xác có một số khác biệt chi tiết liên quan đến điều này
    • 1.55 + [-0.002, 0.002] cho kết quả [1.548, 1.552]
  • Hỗ trợ cú pháp khoảng lồng nhau
    • Có thể nhập [0, [0, 100]] và kết quả là [0, 100]
    • Toàn bộ các số bên trong dùng để xác định biên khoảng cũng đều được diễn giải là khoảng
    • Trong khoảng lồng nhau, khoảng nằm ở vị trí biên sẽ lấy cận trên của khoảng đó
    • Thiết kế này cho phép áp dụng phép toán ngay trên chính biên
    • [0, cos(2*pi)] cho kết quả [0, 1]

Các hàm được hỗ trợ

  • Hỗ trợ hằng số
    • Hỗ trợ inf, , pi, e
    • [-inf, 0] * [-inf, 0] cho kết quả [0, +∞]
  • Hỗ trợ hàm trích xuất biên
    • lo(A) trả về cận dưới
      • lo([1, 2]) cho kết quả [1, 1]
    • hi(A) trả về cận trên
      • hi([1, 2]) cho kết quả [2, 2]
  • Hỗ trợ tính bao ngoài của khoảng
    • hull(A) bao toàn bộ hợp trong một khoảng duy nhất
    • hull([1, 2] U [99, 100]) cho kết quả [1, 100]
  • Hỗ trợ các hàm toán học cơ bản
    • abs(A), ví dụ abs([-10, 5]) cho kết quả [0, 10]
    • sqrt(A), ví dụ sqrt([9, 49]) cho kết quả [3, 7]
    • sqinv(A), ví dụ sqinv([4, 64]) cho kết quả [-8, -2] U [2, 8]
  • Hỗ trợ các hàm logarit và mũ
    • log(A), ví dụ log([0, 1]) cho kết quả [-∞, 0]
    • log2(A), ví dụ log2([64, 1024]) cho kết quả [6, 10]
    • log10(A), ví dụ log10([0.0001, 1]) cho kết quả [-4, 0]
    • exp(A), ví dụ exp([-∞, 0] U [1, 2]) cho kết quả [0, 1] U [2.718, 7.389]
  • Hỗ trợ lượng giác và lượng giác ngược
    • cos(A), ví dụ cos([pi/3, pi]) cho kết quả [-1, 0.5]
    • sin(A), ví dụ sin([pi/6, 5*pi/6]) cho kết quả [0.5, 1]
    • tan(A), ví dụ tan([pi/3, 2*pi/3]) cho kết quả [-∞, -1.732] U [1.732, +∞]
    • acos(A), ví dụ acos([-1/2, 1/2]) cho kết quả [1.047, 2.094]
    • asin(A), ví dụ asin([0, 1]) cho kết quả [0, 1.571]
    • atan(A), ví dụ atan([-10, 2]) cho kết quả [-1.471, 1.107]
  • Hỗ trợ hàm giá trị nhỏ nhất và lớn nhất
    • min(A, B), ví dụ min([1, 2], [0, 6]) cho kết quả [0, 2]
    • max(A, B), ví dụ max([0, 10], [5, 6]) cho kết quả [5, 10]

Chế độ toàn độ chính xác

  • Triển khai làm tròn ra ngoài trên số dấu phẩy động IEEE 754 double precision
    • Sử dụng kiểu number của JavaScript
    • Bảo đảm rằng khoảng kết quả luôn chứa giá trị thực khi tính cùng biểu thức trên số thực với độ chính xác vô hạn
  • Bao gồm trường hợp 0.1 + 0.2
    • 0.3 không thể được biểu diễn chính xác bằng số dấu phẩy động double precision
    • interval arithmetic thực hiện phép tính khoảng có chứa 0.3
  • Hành vi khi bật chế độ toàn độ chính xác
    • Các số do người dùng nhập được diễn giải thành khoảng nhỏ nhất chứa giá trị IEEE 754 gần nhất với biểu diễn thập phân đã nhập, nhưng có hai biên không trùng đúng với giá trị đó
    • Số đầu ra được hiển thị với mọi chữ số thập phân khả dụng
    • Sử dụng Number.toString()
  • Hành vi khi tắt chế độ toàn độ chính xác
    • Các số do người dùng nhập được diễn giải thành khoảng suy biến có hai biên trùng với giá trị IEEE 754 gần nhất của biểu diễn thập phân đã nhập
    • Số đầu ra được hiển thị tối đa 4 chữ số sau dấu thập phân
    • Sử dụng Number.toPrecision()

Lỗi

  • Có đề cập rằng máy tính vẫn có thể còn lỗi
  • Cung cấp liên kết GitHub Issues để báo cáo vấn đề

Mã nguồn mở

  • Cả Interval Calculator và bộ máy tính toán not-so-float đều được công bố mã nguồn mở
  • Có kèm liên kết tài trợ GitHub Sponsors

Công việc sắp tới

  • Dự kiến tách chế độ toàn độ chính xác thành hai mục điều khiển
    • Diễn giải đầu vào
    • Độ chính xác hiển thị
  • Dự kiến thêm biến ans
    • Biến lưu kết quả của lần nhập trước
  • Dự kiến thêm toán tử hoặc hàm giao
  • Dự kiến cải thiện tính trực quan của độ ưu tiên toán tử U
  • Dự kiến hỗ trợ nhập hợp rỗng

1 bình luận

 
Ý kiến Hacker News
  • Với tư cách là tác giả, tôi muốn nói rằng làm tròn ra ngoài là điểm nổi tiếng nhất của interval arithmetic khi xử lý vấn đề độ chính xác, nhưng theo tôi thật tiếc khi người ta chỉ chú ý đến mỗi điều đó. Tính chất bao hàm được nói tới trong các bài nghiên cứu hoạt động ở mọi thang đo, nên các kết quả như 50 * (10 + [-1, 1]) = [450, 550] xuất hiện rất tự nhiên. Nếu chồng thêm một lớp union lên trên, ta còn có thể xử lý cả những thứ như hàm nghịch đảo thực sự của hàm bình phương, và chỉ cần thử sqinv(64) thay vì sqrt là sẽ thấy. Thực ra interval calculator này được tạo ra để thử nghiệm phần cài đặt interval union arithmetic mà tôi đang làm cho một dự án khác là backwards updating spreadsheet. Phần cài đặt là not-so-float, còn các dự án liên quan là bidicalcthảo luận HN
    • Tôi tò mò không biết phép arithmetic mà bạn triển khai khác tiêu chuẩn IEEE 1788 như thế nào. Tôi cũng muốn biết hai bài báo được liên kết có quan hệ gì với tiêu chuẩn đó. Để giải quyết các vấn đề được nhắc trong bài thì có cần phải bắt đầu lại hoàn toàn không, hay vẫn có thể xây dựng trên tiêu chuẩn IEEE?
    • Thực sự rất tuyệt nên tôi định nghịch thêm. Có hai điều tôi đặc biệt tò mò: thứ nhất là việc thêm hàm đa trị sẽ khó đến mức nào. Ví dụ, sẽ rất hay nếu ở asin(1) có thể nhận được toàn bộ tập [pi/2, pi/2] + n[2pi, 2pi] mà không cần Mathematica. Thứ hai là phần mô tả cách diễn giải số do người dùng nhập vào hơi gây bối rối. Theo tôi, các giá trị biên đầu ra của khoảng nhỏ nhất chứa giá trị đầu vào phải là hai số IEEE 754 gần nhất bao lấy giá trị đầu vào, nhưng cách viết hiện tại lại khiến tôi đọc thành kiểu IEEE754(input)+[-epsilon, epsilon], nên cảm giác ý nghĩa bị khác đi
  • Cái này thực sự hay. Công việc của Matt Keeter về implicit surfaces và tối ưu hóa bằng interval math cũng rất đáng xem. Có thể xem nội dung liên quan trong bài thuyết trình này
  • Tôi cũng có một graphing calculator dùng interval arithmetic, nên có lẽ bạn sẽ thấy thú vị. Có thể dùng thử trực tiếp ở formulagraph, còn phần giải thích cách nó hoạt động và mã liên quan thì tôi đã viết trong bài này
    • Ấn tượng đầu tiên của tôi là nó khá giống GrafEq. Tự nhiên nhớ lại GrafEq ngày xưa
  • Tôi cũng thấy chủ đề này thú vị nên từng thử viết một thư viện Math::Interval đơn giản bằng Raku. Đó là raku-Math-Interval, một thử nghiệm được xây dựng dựa trên Junction tích hợp sẵn của Raku và lớp Range, và đó là một trải nghiệm khá thú vị
  • Rất hay, cảm ơn vì đã chia sẻ. Tôi nghĩ sẽ còn tốt hơn nữa nếu interval có thể hiển thị việc bao gồm hay loại trừ cận trên·cận dưới. Ký pháp tôi quen dùng là đặt ngoặc hướng ra ngoài khi giá trị không được bao gồm, và luôn áp dụng như vậy với vô cực. Ví dụ có thể viết ]-∞, -1] U [0.5, +∞[ như vậy, còn khoảng bị loại trừ ở giữa sẽ là ]-1, 0.5[. Theo cách tôi hiểu thì min và max cũng dường như được diễn giải theo kiểu này. Và một ý tưởng UI khác có thể tiện là khi bấm hoặc chạm vào công thức ở vùng kết quả thì nó sẽ được sao chép vào ô nhập liệu
    • Tôi đã đọc bài báo được liên kết, và ở đây họ chỉ mô tả các khoảng đóng. Interval union được định nghĩa là tập các khoảng đóng, tách rời nhau, và chỉ các cận của extreme interval ở hai đầu mới có thể là ±∞
    • Có thể hỗ trợ kiểu ký pháp đó, nhưng mã sẽ phức tạp hơn rất nhiều. Vì vậy tôi đã quyết định không hỗ trợ ngay từ giai đoạn rất sớm. Dù vậy, nó vẫn có thể là một tính năng bổ sung rất hay
    • Tôi cũng thấy chỗ này hơi khó hiểu. Ký pháp chuẩn mà tôi biết là ngoặc tròn, nhưng có lẽ trong môi trường ASCII thì không thật sự phù hợp
  • Rất ấn tượng. Tôi chưa hiểu hoàn toàn mọi phép toán, nhưng chỉ riêng phần tôi hiểu thôi cũng đã thấy rất đáng nể rồi. Tôi thấy giá như ở lớp học mình được tiếp xúc với phép toán trên khoảng sớm hơn một chút thì tốt biết mấy. Trong thống kê cơ bản với khoảng tin cậy hay trong phương trình bậc hai với dấu ± thì những ý niệm tương tự đã xuất hiện, nhưng ta lại không thể tiếp tục tính toán với kết quả đó như một dữ liệu thống nhất mà luôn phải xử lý riêng hai giá trị của dấu ±, điều đó lúc nào cũng khiến tôi thấy hơi tiếc. Tất nhiên tôi hiểu giáo viên muốn nhanh chóng quay lại các ứng dụng nên không đi sâu. Dù vậy, giá như chí ít cũng có một gợi ý rằng loại đối tượng này cũng có thể có phép toán thông thường. Thứ bạn đang cho thấy còn đi xa hơn nhiều, nhưng nó giống như một sự xác nhận rằng việc xem interval như dữ liệu có hành vi riêng của nó là hoàn toàn có lý
  • Tôi từng nghĩ rằng giá như mình biết về interval arithmetic khi lần đầu dùng thư viện khoảng thời gian tick của Clojure thì tốt biết bao. Thư viện này còn có cả phần cài đặt Allen's Interval Algebra, và cũng tiếp nhận khái niệm tập các khoảng rời rạc rất hữu ích cho tính toán thực tế. Ví dụ nó rất hợp với các công việc HR như tính tập các khoảng nghỉ phép thuộc về một năm nào đó. Trước đây tôi chỉ biết đến công trình của Allen, rồi tình cờ mới phát hiện ra lợi ích mà các tập kiểu này mang lại. Mã nằm ở juxt/tick
  • Tôi hoàn toàn thấy được tính hữu ích của công cụ này, nhưng cá nhân tôi lại nghĩ máy tính xác suất sẽ hữu ích hơn. Ví dụ kết quả như 1 / [-1, 2] không cho biết giá trị nào có mức độ hợp lý ra sao, và ngay cả khi giả sử đầu vào là phân bố đều thì đầu ra rõ ràng cũng có vẻ không phải phân bố đều
  • Gần đây tôi cũng triển khai một thứ tương tự, nhưng góc nhìn là về tính thuộc tập hợp. Vì thế để phân tích Boolean đầy đủ cho interval membership thì tôi cần phép bù. Các khoảng ở đây đều là tập đóng nên phần bù sẽ trở thành khoảng mở, nhưng trong trường hợp sử dụng của tôi thì việc có bao gồm điểm cuối hay không không quan trọng, nên tôi không cố phân biệt khoảng mở và khoảng đóng. Hơn nữa, với arithmetic không chính xác thì bản thân việc một tập là mở hay đóng có thể cũng không được xác định rõ
  • Việc mở rộng logic sang union of intervals có vẻ rất hay, nhưng tôi tò mò về độ phức tạp. Nếu một phép toán có thể tạo ra hai khoảng, thì sau N phép toán có vẻ trong trường hợp xấu nhất sẽ có tăng trưởng theo hàm mũ. Khi đó, nếu không đưa vào xấp xỉ sau một số lượng nhất định, nó có thể sẽ không thực tế cho các ứng dụng phổ biến như abstract interpretation
    • Nhận xét đó hoàn toàn đúng, và đây là vấn đề đã được biết rõ trong phía abstract interpretation. Đúng như bạn nói, thông thường người ta đặt một ngưỡng kích thước cho đối tượng, và khi vượt ngưỡng thì sẽ gộp các khoảng lại với nhau. Tuy vậy, ít nhất trong abstract interpretation thì có vẻ nhiều trường hợp còn dùng những miền tinh vi hơn so với interval