Kiểu dữ liệu nào là phân số trong python?

Các ngôn ngữ lập trình hướng đối tượng cho phép lập trình viên tạo các kiểu dữ liệu mới hoạt động giống như các kiểu dữ liệu có sẵn. Chúng ta sẽ khám phá khả năng này bằng cách xây dựng một lớp Phân số hoạt động rất giống với các kiểu số có sẵn. số nguyên, số dài và số float

Phân số, còn được gọi là số hữu tỷ, là các giá trị có thể được biểu thị dưới dạng tỷ lệ của các số nguyên, chẳng hạn như 5/6. Số ở trên gọi là tử số, số ở dưới gọi là mẫu số

Chúng ta bắt đầu bằng cách định nghĩa một lớp Phân số với phương thức khởi tạo cung cấp tử số và mẫu số là số nguyên

phân số lớp
def __init__(bản thân, tử số, mẫu số=1)
bản thân. tử số = tử số
bản thân. mẫu số = mẫu số

Mẫu số là tùy chọn. Phân số chỉ có một tham số đại diện cho một số nguyên. Nếu tử số là n, ta xây dựng Phân số n/1

Bước tiếp theo là viết phương thức __str__ hiển thị phân số theo cách hợp lý. Dạng "tử số/mẫu số" là tự nhiên ở đây

phân số lớp
 
def __str__(bản thân)
trả về "%d/%d" % (tự. tử số, bản thân. mẫu số)

Để kiểm tra những gì chúng tôi có cho đến nay, chúng tôi đặt nó vào một tệp có tên Phân số. py và nhập nó vào trình thông dịch Python. Sau đó, chúng tôi tạo một đối tượng phân số và in nó

>>> từ Phân số nhập Phân số
>>> thư rác = Phân số (5,6)
>>> print "Phân số là", thư rác
Phân số là 5/6

Như thường lệ, lệnh print gọi ngầm phương thức __str__

phép nhân phân số

Chúng tôi muốn có thể áp dụng các phép toán cộng, trừ, nhân và chia bình thường cho các phân số. Để làm điều này, chúng ta có thể quá tải các toán tử toán học cho các đối tượng Phân số

Chúng ta sẽ bắt đầu với phép nhân vì nó dễ thực hiện nhất. Để nhân các phân số, ta tạo một phân số mới có tử số là tích của các tử số ban đầu và mẫu số là tích của các mẫu số ban đầu. __mul__ là tên mà Python sử dụng cho một phương thức quá tải toán tử *

phân số lớp
 
def __mul__(bản thân, người khác)
trả về Phân số (tự. tử số * khác. tử số,
bản thân. mẫu số * khác. mẫu số)

Chúng ta có thể kiểm tra phương pháp này bằng cách tính tích của hai phân số

>>> in Phân số(5,6) * Phân số(3,4)
15/24

Nó hoạt động, nhưng chúng ta có thể làm tốt hơn. Chúng ta có thể mở rộng phương thức để xử lý phép nhân với một số nguyên. Chúng tôi sử dụng hàm isinstance để kiểm tra xem kia có phải là số nguyên không và chuyển đổi nó thành phân số nếu là

phân số lớp
 
def __mul__(bản thân, người khác)
nếu isinstance(khác, int)
khác = Phân số (khác)
trả về Phân số (tự. tử số   * khác. tử số,
bản thân. mẫu số * khác. mẫu số)

Nhân phân số và số nguyên hiện hoạt động, nhưng chỉ khi phân số là toán hạng bên trái

>>> in Phân số(5,6) * 4
20/6
>>> in ra 4 * Phân số(5,6)
LoạiLỗi. __mul__ cũng như __rmul__ được xác định cho các toán hạng này

Để đánh giá một toán tử nhị phân như phép nhân, Python sẽ kiểm tra toán hạng bên trái trước để xem liệu nó có cung cấp một __mul__ hỗ trợ loại toán hạng thứ hai hay không. Trong trường hợp này, toán tử số nguyên tích hợp không hỗ trợ phân số

Tiếp theo, Python kiểm tra toán hạng bên phải để xem liệu nó có cung cấp phương thức __rmul__ hỗ trợ kiểu đầu tiên hay không. Trong trường hợp này, chúng tôi chưa cung cấp __rmul__ nên không thành công

Mặt khác, có một cách đơn giản để cung cấp __rmul__

phân số lớp
 
__rmul__ = __mul__

Nhiệm vụ này nói rằng __rmul__ giống như __mul__. Bây giờ nếu chúng ta đánh giá 4 * Phân số (5,6), Python gọi __rmul__ trên đối tượng Phân số và chuyển 4 làm tham số

>>> in ra 4 * Phân số(5,6)
20/6

Vì __rmul__ giống như __mul__ và __mul__ có thể xử lý một tham số số nguyên, nên chúng ta đã sẵn sàng

cộng phân số

Phép cộng phức tạp hơn phép nhân, nhưng vẫn không quá tệ. Tổng của a/b và c/d là phân số (a*d+c*b)/(b*d)

Sử dụng mã nhân làm mẫu, chúng ta có thể viết __add__ và __radd__

phân số lớp
 
def __add__(bản thân, người khác)
nếu isinstance(khác, int)
khác = Phân số (khác)
trả về Phân số (tự. tử số   * khác. mẫu số +
bản thân. mẫu số * khác. tử số,
bản thân. mẫu số * khác. mẫu số)

__radd__ = __add__

Chúng ta có thể kiểm tra các phương thức này với Phân số và số nguyên

>>> in Phân số(5,6) + Phân số(5,6)
60/36
>>> in Phân số(5,6) + 3
23/6
>>> in 2 + Phân số(5,6)
17/6

Hai ví dụ đầu tiên gọi __add__;

thuật toán Euclid

Trong ví dụ trước, chúng tôi đã tính tổng 5/6 + 5/6 và nhận được 60/36. Điều đó đúng, nhưng đó không phải là cách tốt nhất để trình bày câu trả lời. Để rút gọn phân số về các số hạng đơn giản nhất, chúng ta phải chia tử số và mẫu số cho ước số chung lớn nhất của chúng (GCD), là 12. Kết quả là 5/3

Nói chung, bất cứ khi nào chúng ta tạo một đối tượng Phân số mới, chúng ta nên rút gọn nó bằng cách chia tử số và mẫu số cho GCD của chúng. Nếu phân số đã được giảm, GCD là 1

Euclid của Alexandria (khoảng. 325--265 TCN) trình bày một thuật toán để tìm GCD cho hai số nguyên m và n

Nếu n chia hết m thì n là ƯCLN. Mặt khác, GCD là GCD của n và phần còn lại của m chia cho n

Định nghĩa đệ quy này có thể được biểu diễn chính xác dưới dạng một hàm

def gcd (m, n)
nếu m % n == 0
trả lại n
khác
trả về gcd(n, m%n)

Trong dòng đầu tiên của phần nội dung, chúng tôi sử dụng toán tử mô đun để kiểm tra tính chia hết. Ở dòng cuối cùng, chúng tôi sử dụng nó để tính phần còn lại sau khi chia

Vì tất cả các hoạt động chúng tôi đã viết tạo Phân số mới cho kết quả, chúng tôi có thể giảm tất cả các kết quả bằng cách sửa đổi phương thức khởi tạo

phân số lớp
def __init__(bản thân, tử số, mẫu số=1)
g = gcd (tử số, mẫu số)
bản thân. tử số   =   tử số / g
bản thân. mẫu số = mẫu số / g

Bây giờ, bất cứ khi nào chúng ta tạo một Phân số, nó sẽ được rút gọn về dạng đơn giản nhất

>>> Phân số(100,-36)
-25/9

Một tính năng hay của gcd là nếu phân số âm, dấu trừ luôn được chuyển đến tử số

So sánh phân số

Giả sử chúng ta có hai đối tượng Phân số, a và b, và chúng ta đánh giá a == b. Việc triển khai mặc định == kiểm tra sự bình đẳng nông, do đó, nó chỉ trả về true nếu a và b là cùng một đối tượng

Nhiều khả năng, chúng tôi muốn trả về giá trị true nếu a và b có cùng giá trị     tức là bằng nhau sâu sắc

Chúng ta phải dạy các phân số cách tự so sánh. Như chúng ta đã thấy trong phần , chúng ta có thể nạp chồng tất cả các toán tử so sánh cùng một lúc bằng cách cung cấp một phương thức __cmp__

Theo quy ước, phương thức __cmp__ trả về một số âm nếu self nhỏ hơn other, 0 nếu chúng giống nhau và một số dương nếu self lớn hơn other

Cách đơn giản nhất để so sánh các phân số là nhân chéo. Nếu a/b > c/d thì quảng cáo > bc. Với ý nghĩ đó, đây là mã cho __cmp__

phân số lớp
 
def __cmp__(bản thân, khác)
khác = (tự. tử số * khác. mẫu số -
khác. tử số * tự. mẫu số)
trả lại sự khác biệt

Nếu bản thân lớn hơn người khác, thì diff sẽ dương. Nếu other lớn hơn, thì diff sẽ âm. Nếu chúng giống nhau, diff bằng không

Đưa nó đi xa hơn

Tất nhiên, chúng tôi chưa hoàn thành. Chúng tôi vẫn phải thực hiện phép trừ bằng cách ghi đè __sub__ và chia bằng cách ghi đè __div__

Một cách để xử lý các hoạt động đó là triển khai phủ định bằng cách ghi đè __neg__ và đảo ngược bằng cách ghi đè __invert__. Sau đó, chúng ta có thể trừ bằng cách phủ định toán hạng thứ hai và cộng, và chúng ta có thể chia bằng cách đảo ngược toán hạng thứ hai và nhân

Tiếp theo, chúng tôi phải cung cấp __rsub__ và __rdiv__. Thật không may, chúng ta không thể sử dụng cùng một thủ thuật mà chúng ta đã sử dụng cho phép cộng và phép nhân, bởi vì phép trừ và phép chia không có tính chất giao hoán. Chúng ta không thể đặt __rsub__ và __rdiv__ bằng __sub__ và __div__. Trong các hoạt động này, thứ tự của các toán hạng tạo nên sự khác biệt

Để xử lý phủ định một ngôi, đó là việc sử dụng dấu trừ với một toán hạng duy nhất, chúng tôi ghi đè __neg__

Chúng ta có thể tính lũy thừa bằng cách ghi đè __pow__, nhưng việc triển khai hơi phức tạp. Nếu số mũ không phải là số nguyên, thì có thể không thể biểu thị kết quả dưới dạng Phân số. Ví dụ: Phân số(2) ** Phân số(1,2) là căn bậc hai của 2, là một số vô tỷ (không thể biểu diễn dưới dạng phân số). Vì vậy, không dễ để viết phiên bản chung nhất của __pow__

Có một phần mở rộng khác cho lớp Phân số mà bạn có thể muốn nghĩ đến. Cho đến nay, chúng ta đã giả sử rằng tử số và mẫu số là các số nguyên

Như một bài tập, hoàn thành việc triển khai lớp Phân số để nó xử lý phép trừ, phép chia và lũy thừa

Bảng chú giải

ước số chung lớn nhất (GCD)Số nguyên dương lớn nhất chia không dư cho cả tử số và mẫu số của một phân số. giảmĐể thay đổi một phân số thành dạng tương đương với GCD là 1. phủ định đơn nguyên Phép toán tính toán nghịch đảo cộng, thường được biểu thị bằng dấu trừ ở đầu. Được gọi là "đơn nguyên" trái ngược với phép toán trừ nhị phân, đó là phép trừ

Đây là phiên bản cũ hơn của cuốn sách hiện được gọi là Think Python. Bạn có thể thích đọc một phiên bản mới hơn

Kiểu dữ liệu nào là phân số trong Python?

Trong Python, mô-đun Phân số hỗ trợ số học hữu tỉ . Sử dụng mô-đun này, chúng ta có thể tạo các phân số từ số nguyên, số thực, số thập phân và từ một số giá trị số và chuỗi khác. Có một khái niệm về Fraction Instance. Nó được hình thành bởi một cặp số nguyên là tử số và mẫu số.

Phân số có phải là số nguyên không?

Phân số và số thập phân không phải là số nguyên . Tất cả các số nguyên đều là số nguyên (và tất cả các số tự nhiên đều là số nguyên), nhưng không phải tất cả các số nguyên đều là số nguyên hoặc số tự nhiên.

Phân số có phải là thư viện Python chuẩn không?

Tạo phân số Python từ các loại dữ liệu khác nhau. Không giống như int hay float , phân số không phải là kiểu dữ liệu tích hợp sẵn trong Python , nghĩa là bạn phải nhập một mô-đun tương ứng từ thư viện chuẩn vào .