membagi angka menjadi bagian bilangan bulat dan desimal

91

Apakah ada cara pythonic untuk membagi bilangan 1234.5678menjadi dua bagian (1234, 0.5678)yaitu bilangan bulat dan bilangan desimal?

AA ganda
sumber

Jawaban:

142

Penggunaan math.modf:

import math
x = 1234.5678
math.modf(x) # (0.5678000000000338, 1234.0)
mhyfritz.dll
sumber
2
Sempurna! Berfungsi baik dengan negatif juga! Terima kasih
Double AA
1
setelah menerapkan math.modf (x) bagaimana cara menangani nilai hasil? Misalnya jika saya memasukkan 1234.0 ke variabel, bagaimana saya bisa melakukannya?
hakiko
3
des, int = math.modf (1234.5678)
gbtimmon
17
Jangan gunakan intsebagai nama variabel, itu akan menggantikan intfungsi.
Holloway
2
@Trengot - Gunakan int_jika Anda harus memiliki variabel yang, ketika dibacakan, disebut "int".
ArtOfWarfare
61

Kita bisa menggunakan fungsi built-in yang tidak terkenal; divmod:

>>> s = 1234.5678
>>> i, d = divmod(s, 1)
>>> i
1234.0
>>> d
0.5678000000000338
utdemir
sumber
4
Memberikan hasil yang mungkin tidak intuitif untuk angka negatif: divmod(-4.5,1)memberikan -5.0 dan 0.5. Menggunakan divmod(-4.5, -1)memberikan 4.0 dan -0.5.
Holloway
@Holloway itu bukan tidak intuitif, itu berasal dari aturan matematika: en.wikipedia.org/wiki/Floor_and_ceiling_functions :)
Sviatoslav V.
43
>>> a = 147.234
>>> a % 1
0.23400000000000887
>>> a // 1
147.0
>>>

Jika Anda ingin bagian integer sebagai integer dan bukan float, gunakan int(a//1)saja. Untuk mendapatkan tupel dalam satu bagian:(int(a//1), a%1)

EDIT: Ingatlah bahwa bagian desimal dari angka float adalah perkiraan , jadi jika Anda ingin merepresentasikannya seperti yang dilakukan manusia, Anda perlu menggunakan perpustakaan desimal

Mac
sumber
4
Hasil yang agak membingungkan untuk bilangan negatif, -2.25 // 1 == -3.0dan -2.25 % 1 == 0.75. Ini mungkin yang diinginkan OP, karena bagian int + bagian desimal masih sama dengan nilai aslinya. Sebaliknya math.modf(-2.25) == (-0.25, -2.0),.
Andrew Clark
@ Andrew - poin yang bagus! Saya pikir jawaban @ mhyfritz lebih baik, bagaimanapun!
mac
Bagus - Saya rasa ini akan menjadi cara tercepat dari yang ditampilkan di sini mengingat peringatan Andrew Clark untuk angka negatif
jacanterbury
14
intpart,decimalpart = int(value),value-int(value)

Berfungsi untuk bilangan positif.

Tandai Tebusan
sumber
In [1]: value = 1.89 In [2]: intpart,decimalpart = int(value),value-int(value) In [3]: intpart Out [3]: 1 In [4]: decimalpart Out [4]: 0.8899999999999999
iMom0
1
@ iMom0 - Lihat docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html dan berbagai pertanyaan di situs ini tentang akurasi floating point.
Mark Ransom
7

Varian ini memungkinkan mendapatkan presisi yang diinginkan:

>>> 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)
dann
sumber
4

Ini juga berhasil untuk saya

>>> val_int = int(a)
>>> val_fract = a - val_int
Shameem
sumber
0

Inilah cara saya melakukannya:

num = 123.456
split_num = str(num).split('.')
int_part = int(split_num[0])
decimal_part = int(split_num[1])
Holydrinker
sumber
4
Bergantung pada kasus penggunaan, ini mungkin tidak akan berfungsi untuk angka dengan nol setelah tempat desimal (mis. 123.0456)
Jon
Anda benar: tergantung kasus penggunaan. Jika Anda mencobanya dengan 123.0456 hasilnya adalah int_part = 123 dan decimal_part = 456. Dalam kasus penggunaan saya, saya menemukan "penghapusan nol" berguna :)
holydrinker
0

Jika Anda tidak keberatan menggunakan NumPy, maka:

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)
kmario23
sumber
0

Setelah melihat beberapa jawaban. Saya telah menemukan dua pernyataan ini yang dapat membagi bilangan positif dan negatif menjadi bagian bilangan bulat dan pecahan tanpa mengorbankan akurasi. Pengujian kinerja menunjukkan bahwa dua pernyataan baru lebih cepat daripada math.modf, selama tidak dimasukkan ke dalam fungsi atau metode mereka sendiri.

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

Misalnya 100.1323-> 100, 0.1323dan -100.1323->-100, -0.1323

Skrip uji:

#!/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()')

Keluaran:

         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}

CATATAN:

Pernyataan dapat lebih cepat dengan modulo, tetapi modulo tidak dapat digunakan untuk membagi bilangan negatif menjadi bilangan bulat dan pecahan.

i, f = int(x), x*1e17%1e17/1e17 # x can not be negative
Diblo Dk
sumber