Bir sayıyı tamsayı ve ondalık parçalara bölme


91

Bir sayıyı 1234.5678iki kısma, (1234, 0.5678)yani tamsayı kısmı ve ondalık kısmı ayırmanın pitonik bir yolu var mı ?

Yanıtlar:


142

Kullanım math.modf:

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

2
Mükemmel! Negatiflerle de harika çalışıyor! Teşekkürler
Double AA

1
math.modf (x) 'i uyguladıktan sonra sonuç değerlerini nasıl işleyebilirim? Örneğin bir değişkene 1234.0 varsayarsam, bunu nasıl yapabilirim?
hakiko

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

17
intDeğişken adı olarak kullanmayın , intişlevi geçersiz kılar .
Holloway

2
@Trengot - int_Yüksek sesle okunduğunda "int" olarak adlandırılan bir değişkeniniz olması gerekiyorsa kullanın .
ArtOfWarfare

61

Ünlü olmayan bir yerleşik işlevi kullanabiliriz; divmod:

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

4
Negatif sayılar için muhtemelen sezgisel olmayan sonuçlar verir: divmod(-4.5,1)-5.0 ve 0.5 verir. Kullanmak divmod(-4.5, -1)4.0 ve -0.5 verir.
Holloway

@Holloway sezgisel değil, matematik kurallarından geliyor: en.wikipedia.org/wiki/Floor_and_ceiling_functions :)
Sviatoslav V.

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

Tamsayı kısmını bir tamsayı olarak ve kayan nokta olarak istemiyorsanız, int(a//1)bunun yerine kullanın. Demeti tek bir geçişte elde etmek için:(int(a//1), a%1)

DÜZENLEME: Bir kayan sayının ondalık kısmının yaklaşık olduğunu unutmayın, bu nedenle onu bir insanın yapacağı gibi göstermek istiyorsanız, ondalık kitaplığı kullanmanız gerekir.


4
Negatif sayılar için biraz kafa karıştırıcı sonuçlar -2.25 // 1 == -3.0ve -2.25 % 1 == 0.75. Bu, OP'nin isteyeceği şey olabilir çünkü int kısım + ondalık kısım hala orijinal değere eşittir. Aksine math.modf(-2.25) == (-0.25, -2.0),.
Andrew Clark

@Andrew - iyi nokta! Yine de @ mhyfritz'in cevabının daha iyi olduğunu düşünüyorum!
mac

Güzel - Andrew Clark'ın negatif sayılar konusundaki uyarısını akılda tutarak burada gösterilenler arasında en hızlı yol olacağını düşünüyorum
jacanterbury


7

Bu varyant, istenen hassasiyeti elde etmeyi sağlar:

>>> 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

Bu benim için de çalışıyor

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

0

Ben böyle yapıyorum:

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

4
Kullanım durumuna bağlı olarak, bu muhtemelen ondalık basamaktan sonra sıfır olan sayılar için işe yaramayacaktır (ör. 123.0456)
Jon

Haklısın: kullanım durumuna göre değişir. 123.0456 sonucuyla denerseniz, int_part = 123 ve decimal_part = 456 olur. Kullanım durumlarımda "sıfır kaldırmayı" yararlı buldum :)
holydrinker

0

NumPy kullanmanın sakıncası yoksa, o zaman:

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

Birkaç cevaba baktıktan sonra. Doğruluktan ödün vermeden pozitif ve negatif sayıları tam sayı ve kesir kısımlarına bölebilen bu iki cümle buldum. Performans testi, iki yeni ifadenin, math.modfkendi işlevlerine veya yöntemlerine yerleştirilmedikleri sürece daha hızlı olduğunu gösterir .

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

Örneğin 100.1323-> 100, 0.1323ve -100.1323->-100, -0.1323

Test komut dosyası:

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

Çıktı:

         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}

NOT:

İfade, modulo ile daha hızlı olabilir, ancak modulo, negatif sayıları tam sayı ve kesir parçalarına bölmek için kullanılamaz.

i, f = int(x), x*1e17%1e17/1e17 # x can not be negative
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.