Trên thực tế, không đúng là >>> 3.5 % 0.1 0.099999999999999811 >>> repr(3.5 % 0.1) '0.099999999999999811' >>> str(3.5 % 0.1) '0.1' 4 là >>> 3.5 % 0.1 0.099999999999999811 >>> repr(3.5 % 0.1) '0.099999999999999811' >>> str(3.5 % 0.1) '0.1' 5. Bạn có thể kiểm tra điều này rất dễ dàng:
>>> print(3.5 % 0.1) 0.1 >>> print(3.5 % 0.1 == 0.1) FalseTrong thực tế, trên hầu hết các hệ thống, >>> 3.5 % 0.1 0.099999999999999811 >>> repr(3.5 % 0.1) '0.099999999999999811' >>> str(3.5 % 0.1) '0.1' 4 là >>> 3.5 % 0.1 0.099999999999999811 >>> repr(3.5 % 0.1) '0.099999999999999811' >>> str(3.5 % 0.1) '0.1' 7. Nhưng, trên một số phiên bản của Python, >>> 3.5 % 0.1 0.099999999999999811 >>> repr(3.5 % 0.1) '0.099999999999999811' >>> str(3.5 % 0.1) '0.1' 8 là >>> 3.5 % 0.1 0.099999999999999811 >>> repr(3.5 % 0.1) '0.099999999999999811' >>> str(3.5 % 0.1) '0.1' 5:
>>> 3.5 % 0.1 0.099999999999999811 >>> repr(3.5 % 0.1) '0.099999999999999811' >>> str(3.5 % 0.1) '0.1'Bây giờ, có lẽ bạn đang tự hỏi tại sao >>> 3.5 % 0.1 0.099999999999999811 >>> repr(3.5 % 0.1) '0.099999999999999811' >>> str(3.5 % 0.1) '0.1' 4 là >>> 3.5 % 0.1 0.099999999999999811 >>> repr(3.5 % 0.1) '0.099999999999999811' >>> str(3.5 % 0.1) '0.1' 7 thay vì >>> from decimal import Decimal >>> Decimal('3.5') % Decimal('0.1') Decimal('0.0') >>> print(Decimal('3.5') % Decimal('0.1')) 0.0 >>> (Decimal(7)/2) % (Decimal(1)/10) Decimal('0.0') 2. Đó là vì các vấn đề làm tròn điểm nổi thông thường. Nếu bạn chưa đọc những gì mọi nhà khoa học máy tính nên biết về số học dấu phẩy động, bạn nên hoặc ít nhất là bản tóm tắt wikipedia ngắn gọn về vấn đề cụ thể này.
Cũng lưu ý rằng >>> from decimal import Decimal >>> Decimal('3.5') % Decimal('0.1') Decimal('0.0') >>> print(Decimal('3.5') % Decimal('0.1')) 0.0 >>> (Decimal(7)/2) % (Decimal(1)/10) Decimal('0.0') 3 không phải là >>> from decimal import Decimal >>> Decimal('3.5') % Decimal('0.1') Decimal('0.0') >>> print(Decimal('3.5') % Decimal('0.1')) 0.0 >>> (Decimal(7)/2) % (Decimal(1)/10) Decimal('0.0') 4, đó là >>> from decimal import Decimal >>> Decimal('3.5') % Decimal('0.1') Decimal('0.0') >>> print(Decimal('3.5') % Decimal('0.1')) 0.0 >>> (Decimal(7)/2) % (Decimal(1)/10) Decimal('0.0') 5. Vì vậy, >>> from decimal import Decimal >>> Decimal('3.5') % Decimal('0.1') Decimal('0.0') >>> print(Decimal('3.5') % Decimal('0.1')) 0.0 >>> (Decimal(7)/2) % (Decimal(1)/10) Decimal('0.0') 6 là >>> from decimal import Decimal >>> Decimal('3.5') % Decimal('0.1') Decimal('0.0') >>> print(Decimal('3.5') % Decimal('0.1')) 0.0 >>> (Decimal(7)/2) % (Decimal(1)/10) Decimal('0.0') 7, thậm chí không gần với >>> from decimal import Decimal >>> Decimal('3.5') % Decimal('0.1') Decimal('0.0') >>> print(Decimal('3.5') % Decimal('0.1')) 0.0 >>> (Decimal(7)/2) % (Decimal(1)/10) Decimal('0.0') 8. Đây là khá nhiều cơ bản đối với định nghĩa của mô đun, và nó sai ở Python, và chỉ là mọi ngôn ngữ lập trình khác.
Nhưng Python 3 đến giải cứu ở đó. Hầu hết những người biết về >>> from decimal import Decimal >>> Decimal('3.5') % Decimal('0.1') Decimal('0.0') >>> print(Decimal('3.5') % Decimal('0.1')) 0.0 >>> (Decimal(7)/2) % (Decimal(1)/10) Decimal('0.0') 9 đều biết rằng đó là cách bạn thực hiện "phân chia số nguyên" giữa các số nguyên, nhưng không nhận ra rằng đó là cách bạn thực hiện phân chia tương thích mô đun giữa bất kỳ loại nào. >>> 10 % 3 1 >>> 2 % 2 0 >>> 0 là >>> 10 % 3 1 >>> 2 % 2 0 >>> 1, vì vậy >>> 10 % 3 1 >>> 2 % 2 0 >>> 2 là (ít nhất là trong một lỗi làm tròn nhỏ) >>> from decimal import Decimal >>> Decimal('3.5') % Decimal('0.1') Decimal('0.0') >>> print(Decimal('3.5') % Decimal('0.1')) 0.0 >>> (Decimal(7)/2) % (Decimal(1)/10) Decimal('0.0') 8. Điều này đã được đặt lại thành 2.x, vì vậy (tùy thuộc vào phiên bản và nền tảng chính xác của bạn), bạn có thể dựa vào điều này. Và, nếu không, bạn có thể sử dụng >>> 10 % 3 1 >>> 2 % 2 0 >>> 4, trả về (trong lỗi làm tròn) >>> 10 % 3 1 >>> 2 % 2 0 >>> 5 tất cả các cách trở lại vào thời gian của thời gian. Tất nhiên bạn vẫn mong đợi điều này là >>> 10 % 3 1 >>> 2 % 2 0 >>> 6, không phải >>> 10 % 3 1 >>> 2 % 2 0 >>> 7, nhưng bạn không thể có điều đó vì lỗi làm tròn.
Nếu bạn đang tìm kiếm một bản sửa lỗi nhanh, hãy xem xét sử dụng loại >>> 10 % 3 1 >>> 2 % 2 0 >>> 8:
>>> from decimal import Decimal >>> Decimal('3.5') % Decimal('0.1') Decimal('0.0') >>> print(Decimal('3.5') % Decimal('0.1')) 0.0 >>> (Decimal(7)/2) % (Decimal(1)/10) Decimal('0.0')Đây không phải là một loại thuốc chữa bách bệnh ma thuật - ví dụ, bạn vẫn phải đối phó với lỗi làm tròn bất cứ khi nào giá trị chính xác của một hoạt động không thể đại diện một cách hữu hạn trong cơ sở 10 - nhưng các lỗi làm tròn phù hợp tốt hơn với các trường hợp trực giác của con người mong đợi có vấn đề. . thời gian. Chỉ là nó không hoàn hảo, bởi vì điều đó là không thể.) Nhưng khi bạn biết trước rằng các số của bạn đều có thể thể hiện chính xác trong cơ sở 10 và chúng không cần nhiều chữ số hơn so với độ chính xác mà bạn đã cấu hình, nó sẽ làm việc.
Toán tử modulo Python (%) được sử dụng để có được phần còn lại của một bộ phận. Hoạt động modulo được hỗ trợ cho số nguyên và số điểm nổi.
Cú pháp của toán tử modulo là >>> 9 % 3.0 0.0 >>> 10 % 3.0 1.0 >>> 2. Ở đây, một người khác là cổ tức và người Bỉ là người chia rẽ. Đầu ra là phần còn lại khi A được chia cho b.
Nếu cả hai người và một người khác là số nguyên, thì phần còn lại cũng là một số nguyên. Nếu một trong số chúng nổi, kết quả cũng là một số điểm nổi.
Ví dụ về toán tử mô -đun Python
Hãy cùng xem xét một số ví dụ của toán tử Modulo.
1. Modulo với số nguyên
>>> 10 % 3 1 >>> 2 % 2 0 >>>
2. Modulo với phao
>>> 9 % 3.0 0.0 >>> 10 % 3.0 1.0 >>>
3. Modulo với đầu vào người dùng
x = input("Please enter first number:\n") fx = float(x) y = input("Please enter first number:\n") fy = float(y) print(f'{x} % {y} = {fx % fy}')
Khi chúng tôi nhận được người dùng đã nhập dữ liệu, nó ở dạng chuỗi. Chúng tôi đang sử dụng chức năng tích hợp float () để chuyển đổi chúng thành số điểm nổi. Đó là lý do tại sao phần còn lại là 1.0 chứ không phải 1.
Đề xuất đọc: hàm python input (): Python input() function
4. Ví dụ ZerodivisionError
Nếu ước số là 0, toán tử modulo sẽ ném >>> 9 % 3.0 0.0 >>> 10 % 3.0 1.0 >>> 3. Chúng ta có thể sử dụng khối Try-Except để bắt lỗi.
a = 10.5 b = 0 try: print(f'{a} % {b} = {a % b}') except ZeroDivisionError as zde: print("We cannot divide by 0")
5. Modulo có số âm
Toán tử modulo Python luôn trả về phần còn lại có cùng dấu với ước số. Điều này có thể dẫn đến một số nhầm lẫn với đầu ra.
>>> -5 % 3 1 >>> 5 % -3 -1 >>> -10 % 3 2 >>>
- -5 % 3 = (1 -2*3) % 3 = 1
- 5 % -3 = (-1 * -2 * -3) % 3 = -1
- -10 % 3 = (2 -4*3) % 3 = 2
6. Python Modulo Math.fmod ()
Hành vi của người vận hành % có số âm khác với thư viện nền tảng C. Nếu bạn muốn thao tác modulo hoạt động như lập trình C, bạn nên sử dụng hàm module fmod () Math. Đây là chức năng được đề xuất để có được modulo với số điểm nổi.
>>> import math >>> math.fmod(-5, 3) -2.0 >>> math.fmod(5, -3) 2.0 >>> math.fmod(-10, 3) -1.0 >>>
- fmod (-5, 3) = fmod (-2 -1*3, 3) = -2.0
- fmod (5, -3) = fmod (2 -1*-3, -3) = 2.0
- fmod (-10, 3) = fmod (-1 -3*3, 3) = -1.0
Quá tải toán tử modulo
Chúng tôi có thể quá tải toán tử Modulo bằng cách triển khai chức năng >>> 9 % 3.0 0.0 >>> 10 % 3.0 1.0 >>> 4 trong định nghĩa lớp của chúng tôi.
class Data: def __init__(self, i): self.id = i def __mod__(self, other): print('modulo function called') return self.id % other.id def __str__(self): return f'Data[{self.id}]' d1 = Data(10) d2 = Data(3) print(f'{d1} % {d2} = {d1%d2}')
Output:
>>> 3.5 % 0.1 0.099999999999999811 >>> repr(3.5 % 0.1) '0.099999999999999811' >>> str(3.5 % 0.1) '0.1' 0
Từ nhanh về các vấn đề số học điểm nổi
Chúng tôi sử dụng định dạng nhị phân để lưu trữ các giá trị trong máy tính. Khi nói đến phân số, hầu hết các lần chúng ta có thể đại diện cho chúng chính xác như các phân số nhị phân. Ví dụ, 1/3 có thể được thể hiện ở định dạng nhị phân chính xác và nó sẽ luôn là một giá trị gần đúng.
Đó là lý do tại sao bạn có thể nhận được kết quả bất ngờ khi thực hiện các hoạt động số học với số điểm nổi. Nó rõ ràng từ đầu ra của các hoạt động dưới đây.
>>> 3.5 % 0.1 0.099999999999999811 >>> repr(3.5 % 0.1) '0.099999999999999811' >>> str(3.5 % 0.1) '0.1' 1
Đầu ra phải là 0 vì 3.2*3 là 9,6. Nhưng, các giá trị phân số float không được biểu diễn chính xác và xấp xỉ đang gây ra lỗi này. Nó cũng rõ ràng từ ví dụ này.
>>> 3.5 % 0.1 0.099999999999999811 >>> repr(3.5 % 0.1) '0.099999999999999811' >>> str(3.5 % 0.1) '0.1' 2
Vì vậy, bạn nên chăm sóc thêm khi làm việc với số điểm nổi. Nó khuyên bạn nên thực hiện một vòng và sau đó chỉ so sánh hai số điểm nổi.
>>> 3.5 % 0.1 0.099999999999999811 >>> repr(3.5 % 0.1) '0.099999999999999811' >>> str(3.5 % 0.1) '0.1' 3
References:
- Các vấn đề số học điểm nổi
- ZerodivisionError
- Các nhà khai thác Python
- Math.fmod () API DOC