Thay đổi số thập phân thành phân số trong JS

Jan 11 2023
Tất nhiên có rất nhiều thuật toán phức tạp nằm ngoài bài viết này, từ sách vở, kết quả nghiên cứu, cho đến phòng thí nghiệm siêu máy tính. Nhưng chúng tôi chỉ có một máy tính hoặc máy tính xách tay và chúng tôi muốn chuyển đổi một số thập phân thành một cặp phân số đại diện tốt nhất cho số thập phân.
Ảnh của Volkan Olmez trên Bapt

decToFrac(0.1625)
// get [13, 8] or simply 13 / 8

Tất nhiên có rất nhiều thuật toán phức tạp nằm ngoài bài viết này, từ sách vở, kết quả nghiên cứu, cho đến phòng thí nghiệm siêu máy tính. Nhưng chúng tôi chỉ có một máy tính hoặc máy tính xách tay và chúng tôi muốn chuyển đổi một số thập phân thành một cặp phân số đại diện tốt nhất cho số thập phân. Tại sao tôi dùng từ “đại diện”? Bởi vì khi chúng ta nhận được một số thập phân quá duy nhất, trong số nhiều phân số thay thế mà chúng ta có thể tìm kiếm, không chắc chắn rằng có một số thực sự hoàn hảo để khớp với số thập phân đó.

Tôi, một người mới làm quen với toán học, chỉ với sự tò mò và một chút kiến ​​thức về ngôn ngữ JavaScript, rất muốn tạo ra một hàm có thể chuyển đổi một số thập phân trở lại thành một phân số. Đây là mã JS tôi đã tạo:

decToFrac = dec =>
  [...Array(1000).keys()].flatMap(
    i => [...Array(1000).keys()].map(
      j => [
        i + 1, j + 1, (i + 1) / (j + 1),
        Math.abs(((i + 1) / (j + 1)) - dec)
      ]
    )
  ).sort((a, b) => a[3] - b[3])[0].slice(0, 2)

Tất nhiên, chức năng trên không phải là thuật toán hiệu quả nhất để hoạt động, nhưng ít nhất chúng ta có thể thử 1 triệu khả năng để tìm ra khả năng nào gần nhất với giá trị thập phân mà chúng ta đang nhắm mục tiêu.

decToFrac( 23.689817948712386928365235 )
// get [687, 29] in 2 seconds

687 / 29 // get 23.689655172413794
         // accurate to 3 decimals

Trong dòng thứ hai là một ví dụ về cách nếu chúng ta đếm 687 / 29, bảng điều khiển sẽ hiển thị kết quả 23.689655172413794với 15 chữ số thập phân. Nếu chúng ta so sánh nó với số thập phân mà chúng ta đã cung cấp cho hàm trước đó thì rõ ràng là hai số thập phân không hoàn toàn giống nhau. Nhưng ít nhất chức năng này có thể tính toán với độ chính xác lên đến 3 chữ số thập phân. Nếu nhu cầu của bạn trải rộng từ lĩnh vực kinh tế đến kỹ thuật xây dựng, có lẽ độ chính xác 3 chữ số này đủ đáp ứng nhu cầu công việc của bạn. Nhưng đừng mong đợi chức năng này là giải pháp duy nhất cho nghiên cứu của bạn về toán học hoặc vật lý thuần túy, bởi vì chúng chắc chắn sẽ đòi hỏi độ chính xác cao hơn nhiều.

//            16 digits     /    16 digits
decToFrac( 7528365409872894 / 9876598265498238 )
// get [747, 980] still in 2 seconds

Vậy nếu chúng ta muốn hàm này cho ra những con số chính xác hơn thì sao? Tất nhiên bạn có thể, đơn giản bằng cách sửa đổi chức năng decToFractrên bằng cách mở rộng ma trận hiện có. Ví dụ như thế này:

decToFrac = dec =>
  [...Array(10000).keys()].flatMap( // from 1,000 to 10,000
    i => [...Array(1000).keys()].map(
      j => [
        i + 1, j + 1, (i + 1) / (j + 1),
        Math.abs(((i + 1) / (j + 1)) - dec)
      ]
    )
  ).sort((a, b) => a[3] - b[3])[0].slice(0, 2)

Cảm ơn bạn, và nó có thể hữu ích cho bạn.