Làm thế nào tôi có thể buộc phân chia là điểm nổi? Bộ phận tiếp tục làm tròn xuống 0?


721

Tôi có hai giá trị nguyên ab, nhưng tôi cần tỷ lệ của chúng trong dấu phẩy động. Tôi biết điều đó a < bvà tôi muốn tính toán a / b, vì vậy nếu tôi sử dụng phép chia số nguyên, tôi sẽ luôn nhận được 0 với phần còn lại a.

Làm thế nào tôi có thể buộc ctrở thành một số dấu phẩy động trong Python sau đây?

c = a / b

Chỉ cần nâng cấp lên Python 3.
Boris

Câu trả lời:


807

Trong Python 2, phép chia hai int tạo ra một int. Trong Python 3, nó tạo ra một float. Chúng ta có thể có được hành vi mới bằng cách nhập từ __future__.

>>> from __future__ import division
>>> a = 4
>>> b = 6
>>> c = a / b
>>> c
0.66666666666666663

13
Lưu ý rằng from __future__ import divisionphải ở ngay phần đầu của tệp
yannis

Ngoài ra, vấn đề là nếu bạn muốn phân chia số nguyên ở một nơi nhưng phân chia float ở một nơi khác của tệp ...
mercury0114

1
@ thủy ngân0114: Không thành vấn đề; bạn chỉ sử dụng //khi bạn muốn phân chia sàn và /khi bạn muốn floatphân chia "true" ( ).
ShadowRanger

715

Bạn có thể đúc để nổi bằng cách làm c = a / float(b). Nếu tử số hoặc mẫu số là một số float, thì kết quả cũng sẽ như vậy.


Một cảnh báo: như các nhà bình luận đã chỉ ra, điều này sẽ không hoạt động nếu bcó thể là một cái gì đó không phải là số nguyên hoặc số dấu phẩy động (hoặc một chuỗi đại diện cho một). Nếu bạn có thể giao dịch với các loại khác (chẳng hạn như số phức), bạn sẽ cần kiểm tra những loại đó hoặc sử dụng một phương pháp khác.


195

Làm thế nào tôi có thể buộc phân chia là điểm nổi trong Python?

Tôi có hai giá trị nguyên a và b, nhưng tôi cần tỷ lệ của chúng trong dấu phẩy động. Tôi biết rằng a <b và tôi muốn tính a / b, vì vậy nếu tôi sử dụng phép chia số nguyên, tôi sẽ luôn nhận được 0 với phần còn lại của a.

Làm thế nào tôi có thể buộc c là số dấu phẩy động trong Python sau đây?

c = a / b

Điều thực sự được hỏi ở đây là:

"Làm thế nào để tôi buộc phân chia thực sự như vậy a / bsẽ trả lại một phần?"

Nâng cấp lên Python 3

Trong Python 3, để có được sự phân chia thực sự, bạn chỉ cần làm a / b.

>>> 1/2
0.5

Phân chia tầng, hành vi phân chia cổ điển cho số nguyên, hiện là a // b:

>>> 1//2
0
>>> 1//2.0
0.0

Tuy nhiên, bạn có thể bị kẹt khi sử dụng Python 2 hoặc bạn có thể đang viết mã phải hoạt động trong cả 2 và 3.

Nếu sử dụng Python 2

Trong Python 2, nó không đơn giản như vậy. Một số cách đối phó với phân chia Python 2 cổ điển tốt hơn và mạnh mẽ hơn các cách khác.

Khuyến nghị cho Python 2

Bạn có thể nhận hành vi phân chia Python 3 trong bất kỳ mô-đun đã cho nào với lần nhập sau ở trên cùng:

from __future__ import division

sau đó áp dụng phân chia kiểu Python 3 cho toàn bộ mô-đun. Nó cũng hoạt động trong vỏ trăn tại bất kỳ điểm nào. Trong Python 2:

>>> from __future__ import division
>>> 1/2
0.5
>>> 1//2
0
>>> 1//2.0
0.0

Đây thực sự là giải pháp tốt nhất vì nó đảm bảo mã trong mô-đun của bạn tương thích hơn với Python 3.

Các tùy chọn khác cho Python 2

Nếu bạn không muốn áp dụng điều này cho toàn bộ mô-đun, bạn sẽ bị giới hạn trong một vài cách giải quyết. Phổ biến nhất là ép buộc một trong các toán hạng thành float. Một giải pháp mạnh mẽ là a / (b * 1.0). Trong một vỏ Python tươi:

>>> 1/(2 * 1.0)
0.5

Cũng mạnh mẽ là truedivtừ operatormô-đun operator.truediv(a, b), nhưng điều này có thể chậm hơn vì đó là một cuộc gọi chức năng:

>>> from operator import truediv
>>> truediv(1, 2)
0.5

Không được đề xuất cho Python 2

Thường thấy là a / float(b). Điều này sẽ tăng TypeError nếu b là một số phức. Vì phép chia với số phức được xác định, nên tôi không có phép chia không thành công khi truyền số phức cho số chia.

>>> 1 / float(2)
0.5
>>> 1 / float(2j)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't convert complex to float

Nó không có ý nghĩa với tôi để cố tình làm cho mã của bạn dễ vỡ hơn.

Bạn cũng có thể chạy Python bằng -Qnewcờ, nhưng điều này có nhược điểm là thực thi tất cả các mô-đun với hành vi Python 3 mới và một số mô-đun của bạn có thể mong đợi phân chia cổ điển, vì vậy tôi không khuyên bạn nên làm điều này trừ khi thử nghiệm. Nhưng để chứng minh:

$ python -Qnew -c 'print 1/2'
0.5
$ python -Qnew -c 'print 1/2j'
-0.5j

3
"1 // 2 = 0", "1 // 2.0 = 0.0" - gotcha nhỏ thú vị, ngay cả khi đó là một phép chia số nguyên, nếu bất kỳ toán hạng nào là float thì kết quả là một số nguyên nhưng cũng là float. Tôi đã sử dụng một phân chia số nguyên để tính toán một chỉ mục danh sách và nhận được một lỗi vì điều đó.
R. Navega


66

Trong Python 3.x, dấu gạch chéo đơn ( /) luôn có nghĩa là phân chia đúng (không cắt bớt). ( //Toán tử được sử dụng để cắt bớt phân chia.) Trong Python 2.x (2.2 trở lên), bạn có thể có hành vi tương tự bằng cách đặt một

from __future__ import division

ở đầu mô-đun của bạn.


30

Chỉ cần thực hiện bất kỳ tham số nào để phân chia ở định dạng dấu phẩy động cũng tạo ra đầu ra ở dấu phẩy động.

Thí dụ:

>>> 4.0/3
1.3333333333333333

hoặc là,

>>> 4 / 3.0
1.3333333333333333

hoặc là,

>>> 4 / float(3)
1.3333333333333333

hoặc là,

>>> float(4) / 3
1.3333333333333333

4
Nhưng sau đó bạn có thể bị cám dỗ để làm 1.0 + 1/3hoặc float(c) + a/bhoặc float(a/b)bạn sẽ thất vọng với câu trả lời. Tốt hơn là sử dụng python 3+ hoặc nhập __future__.divisionmô-đun, (xem câu trả lời được chấp nhận), để luôn nhận được câu trả lời bạn mong đợi. Các quy tắc phân chia hiện có tạo ra lỗi toán học xảo quyệt, khó theo dõi.
hobs

@JoeCondron Bạn đã thử python -c 'a=10; b=3.0; print a/b'chưa?
gsbabil

Tôi đã không phải làm thế bởi vì nó rõ ràng hoạt động trong kịch bản này. Tuy nhiên, điều gì xảy ra nếu avà 'b', ví dụ, là đầu ra của hàm số nguyên? Ví dụ a = len(list1), b = len(list2).
JoeCondron

@JoeCondron: điểm tốt. Tôi chỉ cập nhật câu trả lời để bao gồm float(..). Tôi nghĩ rằng nhân với 1.0, như @Pinochle đề xuất dưới đây, cũng có thể hữu ích.
gsbabil

21

Thêm một dấu chấm ( .) để chỉ ra số dấu phẩy động

>>> 4/3.
1.3333333333333333

2
Làm thế nào bạn sẽ áp dụng phương pháp này nếu tử số và mẫu số là cả hai biến?
stackoverflowuser2010

Tôi giả sử bạn tham khảo ví dụ đầu tiên, nếu đó là như vậy, tôi sẽ chỉ sử dụng float()trên một trong các biến.
Alexander

13

Điều này cũng sẽ làm việc

>>> u=1./5
>>> print u
0.2

4
Và bạn sẽ áp dụng cách tiếp cận này như thế nào nếu tử số và mẫu số đều là hai biến?
stackoverflowuser2010

1
Bởi vì nó không hoạt động khi các biến được sử dụng để trừu tượng hóa. Hầu như không có mã có ý nghĩa nào có giá trị được mã hóa cứng như thế.
Keir Simmons

1
Điều này có ít phiếu bầu vì câu trả lời này không trả lời câu hỏi và hoàn toàn không phải là câu trả lời. Trong một câu trả lời, điều quan trọng đầu tiên là chỉ ra lý do tại sao điều này hoạt động. Rất đơn giản: nếu tử số hoặc mẫu số là một số float, kết quả sẽ là một số float. Thông thường, bạn không sử dụng python như một máy tính văn bản, vì vậy bạn muốn có câu trả lời cho các biến ab.
TimZaman

Trong thời gian dài nhất, tôi thực sự nghĩ ./là một toán tử hợp lệ trong python cho phép bạn thực hiện phép chia dấu phẩy động. Đây là lý do tại sao nên sử dụng khoảng trắng một cách thận trọng, trong bất kỳ ngôn ngữ lập trình nào
smac89

6

Nếu bạn muốn sử dụng phân chia "true" (dấu phẩy động) theo mặc định, có một cờ dòng lệnh:

python -Q new foo.py

Có một số nhược điểm (từ PEP):

Người ta đã lập luận rằng một tùy chọn dòng lệnh để thay đổi mặc định là xấu. Nó chắc chắn có thể nguy hiểm trong tay kẻ xấu: ví dụ, không thể kết hợp gói thư viện của bên thứ 3 yêu cầu -Nnew với một gói khác yêu cầu -Qold.

Bạn có thể tìm hiểu thêm về các giá trị cờ khác thay đổi / cảnh báo - về hành vi phân chia bằng cách xem trang man python.

Để biết chi tiết đầy đủ về các thay đổi của bộ phận, hãy đọc: PEP 238 - Thay đổi Toán tử bộ phận


2
from operator import truediv

c = truediv(a, b)

2
Tuy nhiên, điều đó không lý tưởng vì nó không hoạt động trong trường hợp aint và blà float. Một giải pháp tốt hơn dọc theo cùng một dòng là làm from operator import truedivvà sau đó sử dụng truediv(a, b).
Đánh dấu Dickinson

Uh, đúng vậy. Tôi đã giả sử cả hai số nguyên vì đây là lần duy nhất khi ops phân chia khác nhau nhưng bạn thực sự muốn một giải pháp chung. Tôi thực sự không biết bạn có thể nhập toán tử hoặc nó hoàn toàn không hoạt động đối với các ước số float. Trả lời chỉnh sửa.
JoeCondron

1
from operator import truediv

c = truediv(a, b)

trong đó a là cổ tức và b là ước số. Hàm này rất hữu ích khi thương sau khi chia hai số nguyên là số float.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.