tách một số thành phần nguyên và phần thập phân


91

Có một cách thú vị để chia một số chẳng hạn như 1234.5678thành hai phần (1234, 0.5678)tức là phần nguyên và phần thập phân?

Câu trả lời:


142

Sử dụng math.modf:

import math
x = 1234.5678
math.modf(x) # (0.5678000000000338, 1234.0)

2
Hoàn hảo! Hoạt động tuyệt vời với âm bản quá! Cảm ơn
Double AA

1
Sau khi áp dụng math.modf (x), làm cách nào để xử lý các giá trị kết quả? Ví dụ: nếu tôi giả định 1234.0 cho một biến, làm thế nào tôi có thể làm điều đó?
hakiko

3
dec, int = math.modf (1234.5678)
gbtimmon

17
Không sử dụng intlàm tên biến, nó sẽ ghi đè lên inthàm.
Holloway

2
@Trengot - Sử dụng int_nếu bạn phải có một biến mà khi đọc to, được gọi là "int".
ArtOfWarfare

61

Chúng ta có thể sử dụng một hàm tích hợp không nổi tiếng; divmod:

>>> s = 1234.5678
>>> i, d = divmod(s, 1)
>>> i
1234.0
>>> d
0.5678000000000338

4
Cho kết quả có thể không trực quan đối với các số âm: divmod(-4.5,1)cho -5,0 và 0,5. Sử dụng divmod(-4.5, -1)cho kết quả là 4,0 và -0,5.
Holloway

@Holloway nó không phải là không trực quan, nó đến từ các quy tắc toán học: en.wikipedia.org/wiki/Floor_and_ceiling_functions :)
Sviatoslav V.

43
>>> a = 147.234
>>> a % 1
0.23400000000000887
>>> a // 1
147.0
>>>

Nếu bạn muốn phần nguyên là số nguyên chứ không phải số thực, hãy sử dụng int(a//1)thay thế. Để lấy tuple trong một đoạn văn:(int(a//1), a%1)

CHỈNH SỬA: Hãy nhớ rằng phần thập phân của một số thực là gần đúng , vì vậy nếu bạn muốn biểu diễn nó như con người sẽ làm, bạn cần sử dụng thư viện thập phân


4
Kết quả hơi khó hiểu đối với số âm -2.25 // 1 == -3.0-2.25 % 1 == 0.75. Đây có thể là những gì OP muốn, vì phần int + phần thập phân vẫn bằng giá trị ban đầu. Ngược lại math.modf(-2.25) == (-0.25, -2.0),.
Andrew Clark,

@Andrew - điểm tốt! Dù sao thì tôi nghĩ câu trả lời của @ mhyfritz là câu trả lời hay hơn!
mac

Nice - Tôi nghĩ đây sẽ là cách nhanh nhất trong những trình bày ở đây mang trong caveat tâm Andrew Clark cho số âm
jacanterbury


7

Biến thể này cho phép nhận được độ chính xác mong muốn:

>>> a = 1234.5678
>>> (lambda x, y: (int(x), int(x*y) % y/y))(a, 1e0)
(1234, 0.0)
>>> (lambda x, y: (int(x), int(x*y) % y/y))(a, 1e1)
(1234, 0.5)
>>> (lambda x, y: (int(x), int(x*y) % y/y))(a, 1e15)
(1234, 0.5678)

4

Điều này cũng hiệu quả với tôi

>>> val_int = int(a)
>>> val_fract = a - val_int

0

Đây là cách tôi làm điều đó:

num = 123.456
split_num = str(num).split('.')
int_part = int(split_num[0])
decimal_part = int(split_num[1])

4
Tùy thuộc vào trường hợp sử dụng, điều này có thể sẽ không hoạt động đối với các số có số 0 sau vị trí thập phân (ví dụ: 123.0456)
Jon

Bạn nói đúng: nó phụ thuộc vào trường hợp sử dụng. Nếu bạn thử nó với 123.0456 kết quả là int_part = 123 và decimal_part = 456. Trong trường hợp sử dụng của tôi, tôi tìm thấy "việc loại bỏ không" hữu ích :)
holydrinker

0

Nếu bạn không phiền khi sử dụng NumPy, thì:

In [319]: real = np.array([1234.5678])

In [327]: integ, deci = int(np.floor(real)), np.asscalar(real % 1)

In [328]: integ, deci
Out[328]: (1234, 0.5678000000000338)

0

Sau khi xem xét một số câu trả lời. Tôi đã nghĩ ra hai câu lệnh này có thể chia số dương và số âm thành các phần nguyên và phân số mà không ảnh hưởng đến độ chính xác. Kiểm tra hiệu suất cho thấy rằng hai câu lệnh mới nhanh hơn math.modf, miễn là chúng không được đưa vào hàm hoặc phương thức của riêng chúng.

i = int(x) # i contains a positive or negative integer
f = (x*1e17-i*1e17)/1e17 # f contains a positive or negative fraction

Ví dụ 100.1323-> 100, 0.1323-100.1323->-100, -0.1323

Tập lệnh thử nghiệm:

#!/usr/bin/env python
import math
import cProfile

""" Get the performance of both statements vs math.modf. """

X = -100.1323
LOOPS = range(5*10**6)

def fun_a():
    """ The integer part (i) is an integer, and
        the fraction part (f) is a float.
        NOTE: I think this is the most correct way. """
    for _ in LOOPS:
        i = int(X) # -100
        f = (X*1e17-i*1e17)/1e17 # -0.1323

def fun_b():
    """ The integer (i) and fraction (f) part will
        come out as float.
        NOTE: The only difference between this
              and math.modf is the accuracy. """
    for _ in LOOPS:
        i = int(X) # -100
        i, f = float(i), (X*1e17-i*1e17)/1e17 # (-100.0, -0.1323)

def fun_c():
    """ Performance test of the statements in a function.
        The integer part (i) is an integer, and
        the fraction part (f) is a float. """
    def modf(x):
        i = int(x)
        return i, (x*1e17-i*1e17)/1e17

    for _ in LOOPS:
        i, f = modf(X) # (-100, -0.1323)

def fun_d():
    for _ in LOOPS:
        f, i = math.modf(X) # (-100.0, -0.13230000000000075)

def fun_e():
    """ Convert the integer part to integer. """
    for _ in LOOPS:
        f, i = math.modf(X) # (-100.0, -0.13230000000000075)
        i = int(i) # -100

if __name__ == '__main__':
    cProfile.run('fun_a()')
    cProfile.run('fun_b()')
    cProfile.run('fun_c()')
    cProfile.run('fun_d()')
    cProfile.run('fun_e()')

Đầu ra:

         4 function calls in 1.312 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    1.312    1.312 <string>:1(<module>)
        1    1.312    1.312    1.312    1.312 new1.py:10(fun_a)
        1    0.000    0.000    1.312    1.312 {built-in method builtins.exec}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}


         4 function calls in 1.887 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    1.887    1.887 <string>:1(<module>)
        1    1.887    1.887    1.887    1.887 new1.py:17(fun_b)
        1    0.000    0.000    1.887    1.887 {built-in method builtins.exec}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}


         5000004 function calls in 2.797 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    2.797    2.797 <string>:1(<module>)
        1    1.261    1.261    2.797    2.797 new1.py:23(fun_c)
  5000000    1.536    0.000    1.536    0.000 new1.py:27(modf)
        1    0.000    0.000    2.797    2.797 {built-in method builtins.exec}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}


         5000004 function calls in 1.852 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    1.852    1.852 <string>:1(<module>)
        1    1.050    1.050    1.852    1.852 new1.py:34(fun_d)
        1    0.000    0.000    1.852    1.852 {built-in method builtins.exec}
  5000000    0.802    0.000    0.802    0.000 {built-in method math.modf}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}


         5000004 function calls in 2.467 seconds

   Ordered by: standard name

   ncalls  tottime  percall  cumtime  percall filename:lineno(function)
        1    0.000    0.000    2.467    2.467 <string>:1(<module>)
        1    1.652    1.652    2.467    2.467 new1.py:38(fun_e)
        1    0.000    0.000    2.467    2.467 {built-in method builtins.exec}
  5000000    0.815    0.000    0.815    0.000 {built-in method math.modf}
        1    0.000    0.000    0.000    0.000 {method 'disable' of '_lsprof.Profiler' objects}

GHI CHÚ:

Câu lệnh có thể nhanh hơn với modulo, nhưng modulo không thể được sử dụng để chia số âm thành phần nguyên và phần phân số.

i, f = int(x), x*1e17%1e17/1e17 # x can not be negative
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.