Sunday, 5 March 2017

[Python] fractions - tính toán phân số trên Python

Trong một bài viết gần đây, chúng tôi đã giải thích hiện tượng "kỳ lạ" khi 0.1 + 0.1 + 0.1 KHÔNG BẰNG 0.3 khi sử dụng Python hay nhiều ngôn ngữ lập trình khác (C, Java, PHP, Ruby, Golang ...). Nếu bạn vẫn còn thấy nó chưa hết lạ, bấm vào đây để làm quen.

Một giải pháp xử lý vấn đề này là sử dụng thư viện "fractions" có sẵn của Python để tính toán các số hữu tỷ (phân số - rational number). Tập số hữu tỷ được ký hiệu là tập Q khi học ở phổ thông:
các tập số
Thư viện ``fractions`` có một kiểu dữ liệu tên là Fraction, nó giúp biểu diễn các phân số và thực hiện tính toán trên Python. Fraction có thể nhận nhiều dạng đầu vào khác nhau:
- Tử số và mẫu số
- String biểu diễn phân số
- Một số integer hay float
Các đoạn code sử dụng Python 3 với IPython.

Ta import thư viện trước:
In [3]: from fractions import Fraction as F
Đầu vào là tử số và mẫu số:
In [4]: F(16, 10)
Out[4]: F(8, 5)
Thấy Python tự tối giản phân số.









String biểu diễn phân số
In [7]: F('10/2')
Out[7]: Fraction(5, 1)
Nhận vào số nguyên (integer)
In [6]: F(123)
Out[6]: Fraction(123, 1)
Nhận vào số thực (kiểu float)
In [17]: F(0.1)
Out[17]: Fraction(3602879701896397, 36028797018963968)
Ta thấy ở đây, Fraction đã biểu diễn chính xác giá trị "ẩn dưới" kiểu float. Bởi kiểu float không biểu diễn chính xác được giá trị 0.1 mà chỉ xấp xỉ nó bằng một phân số. Do vậy tổng của 3 phân số float 0.1 sẽ không bằng 0.3:
In [18]: F(0.1) + F(0.1) + F(0.1)
Out[18]: Fraction(10808639105689191, 36028797018963968)
In [37]: F(0.3)
Out[37]: Fraction(5404319552844595, 18014398509481984)
Để biểu diễn giá trị 0.1, ta dùng phân số 1/10:
In [21]: F(1,10) + F(1,10) + F(1,10)
Out[21]: Fraction(3, 10)
In [23]: F('1/10') +F('1/10') + F('1/10')
Out[23]: Fraction(3, 10)
Để thu được dạng float của phân số biểu diễn bởi kiểu Fraction, ta dùng function float:
In [31]: F(1,8)
Out[31]: Fraction(1, 8)

In [32]: float(F(1,8))
Out[32]: 0.125
Bài tập:
Tìm tập các bộ số nguyên a,b,c thoả mãn a + b/c = 10 với a,b,c thuộc tập [1,10)

Bài giải:
In [35]: for a in range(1, 10):
    ...:     for b in range(1, 10):
    ...:         for c in range(1, 10):
    ...:             if F(a) + F(b,c) == 10:
    ...:                 print(a,b,c, sep=',', end=' ')
    ...:
    ...:
1,9,1 2,8,1 3,7,1 4,6,1 5,5,1 6,4,1 6,8,2 7,3,1 7,6,2 7,9,3 8,2,1 8,4,2 8,6,3 8,8,4 9,1,1 9,2,2 9,3,3 9,4,4 9,5,5 9,6,6 9,7,7 9,8,8 9,9,9

Hết.

Bạn có thắc mắc về Python không biết hỏi ai? vào ngay http://invite.pymi.vn/
Bạn muốn học Python? đăng ký tại: https://pymi.vn/

HVN at http://www.familug.org/ and http://pymi.vn