Cách kiểm tra nếu giá trị float là toàn bộ số


202

Tôi đang cố gắng tìm ra khối lập phương lớn nhất là toàn bộ số đó, chưa đến 12.000.

processing = True
n = 12000
while processing:
    n -= 1
    if n ** (1/3) == #checks to see if this has decimals or not

Tôi không chắc chắn làm thế nào để kiểm tra nếu nó là một số nguyên hay không! Tôi có thể chuyển đổi nó thành một chuỗi sau đó sử dụng lập chỉ mục để kiểm tra các giá trị cuối và xem liệu chúng có bằng 0 hay không, điều đó có vẻ khá cồng kềnh. đó có phải là cách dễ hơn?


3
nó sẽ làm cho nó dễ dàng hơn để làm việc từ căn bậc n -> (n * n * n <12000)
suspectus

Câu trả lời:


367

Để kiểm tra xem giá trị float có phải là số nguyên hay không, hãy sử dụng float.is_integer()phương thức :

>>> (1.0).is_integer()
True
>>> (1.555).is_integer()
False

Phương thức đã được thêm vào floatloại trong Python 2.6.

Hãy xem xét rằng trong Python 2, 1/30(phép chia tầng cho toán hạng nguyên!) Và số học dấu phẩy động có thể không chính xác (a floatlà một xấp xỉ sử dụng phân số nhị phân, không phải là số thực chính xác). Nhưng điều chỉnh vòng lặp của bạn một chút điều này mang lại:

>>> for n in range(12000, -1, -1):
...     if (n ** (1.0/3)).is_integer():
...         print n
... 
27
8
1
0

điều đó có nghĩa là bất cứ thứ gì trên 3 khối, (bao gồm 10648) đã bị bỏ lỡ do sự thiếu chính xác đã nói ở trên:

>>> (4**3) ** (1.0/3)
3.9999999999999996
>>> 10648 ** (1.0/3)
21.999999999999996

Thay vào đó, bạn phải kiểm tra các số gần với toàn bộ số hoặc không sử dụng float()để tìm số của mình. Giống như làm tròn xuống khối lập phương của 12000:

>>> int(12000 ** (1.0/3))
22
>>> 22 ** 3
10648

Nếu bạn đang sử dụng Python 3.5 hoặc mới hơn, bạn có thể sử dụng math.isclose()hàm để xem giá trị của dấu phẩy động có nằm trong lề có thể định cấu hình hay không:

>>> from math import isclose
>>> isclose((4**3) ** (1.0/3), 4)
True
>>> isclose(10648 ** (1.0/3), 22)
True

Đối với các phiên bản cũ hơn, việc triển khai chức năng đó một cách ngây thơ (bỏ qua kiểm tra lỗi và bỏ qua vô cực và NaN) như được đề cập trong PEP485 :

def isclose(a, b, rel_tol=1e-9, abs_tol=0.0):
    return abs(a - b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)

Không biết trăn, loại tuyên bố này sẽ khiến tôi lo lắng vì nó dường như đòi hỏi toán học hoàn hảo để làm việc trong thế giới thực.
Peter M

1
@PeterM: Phương thức thực sự chỉ trả về Truenếu không có số thập phân nào cả. Có thể có một sự hiểu lầm từ phía OP về số học và độ chính xác của dấu phẩy động, tất nhiên.
Martijn Pieters

1
@MartijnPieters Vâng và một cú trượt nhỏ trong phép tính dấu phẩy động và thật bất ngờ khi bạn có những số thập phân nhỏ, không mong muốn này như 0,00000000000000000101
Peter M

1
@PeterM: và trong Python 2, biểu diễn mặc định sẽ làm tròn đến 16 chữ số; 1.0000000000000001được hiển thị dưới dạng 1.0, trong 3 biểu diễn chuỗi ngắn nhất tạo ra cùng một giá trị được hiển thị.
Martijn Pieters

Bạn range(12000, -1, -1)có thể (imo, sạch sẽ hơn) được viết lại thànhreversed(range(12000+1))
cs95

36

Chúng ta có thể sử dụng toán tử modulo (%). Điều này cho chúng ta biết chúng ta có bao nhiêu phần còn lại khi chia x cho y - biểu thị là x % y. Mỗi số nguyên phải chia cho 1, vì vậy nếu có một số còn lại, nó không phải là một số nguyên.

Hàm này sẽ trả về một boolean, Truehoặc False, tùy thuộc vào việc có phải nlà một số nguyên hay không.

def is_whole(n):
    return n % 1 == 0

15

Bạn có thể sử dụng điều này:

if k == int(k):
    print(str(k) + " is a whole number!")

5
nó thất bại cho số lượng lớn hơn trong khi .is_integer()tiếp tục làm việc.
jfs

Liên kết của bạn IMHO không cho thấy rằng nó không hoạt động. Nó chỉ cho thấy những chiếc phao lớn mất độ chính xác. is_integersử dụng một phương thức tương tự ( o = (floor(x) == x) ? Py_True : Py_False;). Nhưng tôi đồng ý, người ta nên sử dụng is_integer()vì nó rõ ràng hơn nhiều.
Juri Robl

1
Đúng. Nó chỉ cho thấy rằng float lớn có thể mất độ chính xác tức là, large_float == large_intcó thể thất bại ngay cả khi large_float == float(large_int).
jfs

2
123456789012345678901234567890.0 != 123456789012345678901234567890nhưng123456789012345678901234567890.0 == float(123456789012345678901234567890)
jfs

2
Vâng, nhưng k = 123456789012345678901234567890.0sau đó k == int(k)là True, đó là câu trả lời chính xác.
Juri Robl

9

Bạn không cần phải lặp hoặc kiểm tra bất cứ điều gì. Chỉ cần lấy một khối lập phương 12.000 và làm tròn nó xuống:

r = int(12000**(1/3.0))
print r*r*r # 10648

Đây là một câu trả lời hợp lý.
hughdbrown

7

Bạn có thể sử dụng một hoạt động modulo cho điều đó.

if (n ** (1.0/3)) % 1 != 0:
    print("We have a decimal number here!")

2
nếu nlà 6.2, 6.0, 6.12312412, tất cả chúng ta đều có "We have a decimal number here!"?
Jay Wong

@JayWong không chắc bạn đã tải bài kiểm tra của mình như thế nào, nhưng điều này hoạt động tốt trên máy của tôi bằng Python3.7.
Zchpyvr

6

Sẽ không dễ dàng hơn để kiểm tra các rễ khối? Bắt đầu với 20 (20 ** 3 = 8000) và tăng lên 30 (30 ** 3 = 27000). Sau đó, bạn phải kiểm tra ít hơn 10 số nguyên.

for i in range(20, 30):
    print("Trying {0}".format(i))
    if i ** 3 > 12000:
        print("Maximum integral cube root less than 12000: {0}".format(i - 1))
        break

1
Hơn nữa, phao có lỗi làm tròn để bạn có thể bỏ lỡ số khi tính nếu n**(1/3)là số nguyên. Ví dụ: trên máy tính của tôi `10648 ** (1/3) = 21.999999999999996` thay vì 22: vấn đề! Với phương pháp trả lời này, không có vấn đề như vậy. Tôi nghĩ rằng đây là giải pháp đúng duy nhất theo quan điểm toán học (các giải pháp khác là chính xác của Python).
JPG


3

Các câu trả lời trên làm việc cho nhiều trường hợp nhưng họ bỏ lỡ một số. Hãy xem xét những điều sau đây:

fl = sum([0.1]*10)  # this is 0.9999999999999999, but we want to say it IS an int

Sử dụng điều này làm điểm chuẩn, một số đề xuất khác không có hành vi mà chúng tôi có thể muốn:

fl.is_integer() # False

fl % 1 == 0     # False

Thay vào đó hãy thử:

def isclose(a, b, rel_tol=1e-09, abs_tol=0.0):
    return abs(a-b) <= max(rel_tol * max(abs(a), abs(b)), abs_tol)

def is_integer(fl):
    return isclose(fl, round(fl))

bây giờ chúng tôi nhận được:

is_integer(fl)   # True

iscloseđi kèm với Python 3.5+ và đối với các Python khác, bạn có thể sử dụng định nghĩa gần như tương đương này (như được đề cập trong PEP tương ứng )


1
math.fsum([0.1] * 10) == 1
Acumenus

1

Chỉ cần một thông tin bên, is_integerlà làm nội bộ:

import math
isInteger = (math.floor(x) == x)

Không chính xác trong python, nhưng việc thực hiện cpython được thực hiện như đã đề cập ở trên.


1

Tất cả các câu trả lời là tốt nhưng một phương pháp chữa cháy chắc chắn sẽ là

def whole (n):
     return (n*10)%10==0

Hàm trả về Đúng nếu là toàn bộ số khác Sai .... Tôi biết tôi hơi muộn nhưng đây là một trong những phương pháp thú vị mà tôi đã thực hiện ...

Chỉnh sửa: như đã nêu trong nhận xét bên dưới, một bài kiểm tra tương đương rẻ hơn sẽ là:

def whole(n):
    return n%1==0

1
Điều này sẽ không có chức năng khác nhau hơn n % 1 == 0. Trong trường hợp này, bạn đang thực hiện hai thao tác tốn kém hơn cho thử nghiệm tương đương rẻ hơn.
Zchpyvr

0
>>> def is_near_integer(n, precision=8, get_integer=False):
...     if get_integer:
...         return int(round(n, precision))
...     else:
...         return round(n) == round(n, precision)
...
>>> print(is_near_integer(10648 ** (1.0/3)))
True
>>> print(is_near_integer(10648 ** (1.0/3), get_integer=True))
22
>>> for i in [4.9, 5.1, 4.99, 5.01, 4.999, 5.001, 4.9999, 5.0001, 4.99999, 5.000
01, 4.999999, 5.000001]:
...     print(i, is_near_integer(i, 4))
...
4.9 False
5.1 False
4.99 False
5.01 False
4.999 False
5.001 False
4.9999 False
5.0001 False
4.99999 True
5.00001 True
4.999999 True
5.000001 True
>>>

Dưới đây là một số hướng dẫn cho Làm thế nào để tôi viết một câu trả lời tốt? . Câu trả lời được cung cấp này có thể đúng, nhưng nó có thể được hưởng lợi từ một lời giải thích. Mã chỉ trả lời không được coi là câu trả lời "tốt". Từ đánh giá .
Trenton McKinney

-1

Hãy thử sử dụng:

int(val) == val

Nó sẽ cho độ chính xác cao hơn nhiều so với bất kỳ phương pháp nào khác.


Bạn có thể đưa ra một ví dụ để sao lưu tuyên bố rằng "Nó sẽ cho độ chính xác cao hơn nhiều"? Điều này dường như vô căn cứ.
Đánh dấu Dickinson

-1

Bạn có thể sử dụng roundhàm để tính giá trị.

Có trong python như nhiều người đã chỉ ra khi chúng ta tính giá trị của một khối lập phương, nó sẽ cung cấp cho bạn một đầu ra với một chút lỗi. Để kiểm tra xem giá trị có phải là số nguyên hay không, bạn có thể sử dụng hàm sau:

def cube_integer(n):
    if round(n**(1.0/3.0))**3 == n:
        return True
    return False

Nhưng hãy nhớ rằng int(n)nó tương đương với math.floorvà vì điều này nếu bạn tìm thấy int(41063625**(1.0/3.0))bạn sẽ nhận được 344 thay vì 345.

Vì vậy, hãy cẩn thận khi sử dụng intrễ cây lập phương.

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.