【发布时间】:2011-10-04 15:14:57
【问题描述】:
有没有一种 Python 的方法可以将 1234.5678 这样的数字分成两部分 (1234, 0.5678),即整数部分和小数部分?
【问题讨论】:
标签: python
有没有一种 Python 的方法可以将 1234.5678 这样的数字分成两部分 (1234, 0.5678),即整数部分和小数部分?
【问题讨论】:
标签: python
这将完成任务,而不会丢失前导零(如 Holydrinker 的答案):
代码
def extract_int_decimal():
'''get the integer and decimal parts of a given number
by converting it to string and using split method
'''
num = 1234.5678
split_num = str(num).split('.')
int_part = int(split_num[0])
decimal_part = int(split_num[1]) * 10 ** -len(split_num[1])
print("integer part:",int_part)
print("decimal part:",decimal_part)
extract_int_decimal()
结果
integer part: 1234
decimal part: 0.5678000000000001
【讨论】:
我想出了两个语句,可以将正数和负数分成整数和分数,而不会影响准确性(位溢出)和速度。
例如,值100.1323的正值或负值将被划分为:100.1323 -> (100, 0.1323)-100.1323 -> (@ 987654327@,-0.1323)
代码
# Divide a number (x) into integer and fraction
i = int(x) # Get integer
f = (x*1e17 - i*1e17) / 1e17 # Get fraction
速度测试
性能测试表明这两条语句比math.modf快,只要不放入自己的函数或方法中即可。
test.py:
#!/usr/bin/env python
import math
import cProfile
""" Get the performance of both statements and math.modf """
X = -100.1323 # The number to be divided into integer and fraction
LOOPS = range(5 * 10 ** 6) # Number of loops
def scenario_a():
""" Get the performance of the statements """
for _ in LOOPS:
i = int(X) # -100
f = (X*1e17-i*1e17)/1e17 # -0.1323
def scenario_b():
""" Tests the speed of the statements when integer need to be 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 scenario_c():
""" Tests the speed of the statements in a function """
def modf(x):
i = int(x)
return i, (x*1e17-i*1e17)/1e17
for _ in LOOPS:
i, f = modf(X) # (-100, -0.1323)
def scenario_d():
""" Tests the speed of math.modf """
for _ in LOOPS:
f, i = math.modf(X) # (-0.13230000000000075, -100.0)
def scenario_e():
""" Tests the speed of math.modf when the integer part should be integer """
for _ in LOOPS:
f, i = math.modf(X) # (-0.13230000000000075, -100.0)
i = int(i) # -100
if __name__ == '__main__':
cProfile.run('scenario_a()')
cProfile.run('scenario_b()')
cProfile.run('scenario_c()')
cProfile.run('scenario_d()')
cProfile.run('scenario_e()')
结果:
4 function calls in 1.357 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 1.357 1.357 <string>:1(<module>)
1 1.357 1.357 1.357 1.357 test.py:11(scenario_a)
1 0.000 0.000 1.357 1.357 {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.858 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 1.858 1.858 <string>:1(<module>)
1 1.858 1.858 1.858 1.858 test.py:18(scenario_b)
1 0.000 0.000 1.858 1.858 {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.744 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 2.744 2.744 <string>:1(<module>)
1 1.245 1.245 2.744 2.744 test.py:26(scenario_c)
5000000 1.499 0.000 1.499 0.000 test.py:29(modf)
1 0.000 0.000 2.744 2.744 {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.904 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 1.904 1.904 <string>:1(<module>)
1 1.073 1.073 1.904 1.904 test.py:37(scenario_d)
1 0.000 0.000 1.904 1.904 {built-in method builtins.exec}
5000000 0.831 0.000 0.831 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.547 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 2.547 2.547 <string>:1(<module>)
1 1.696 1.696 2.547 2.547 test.py:43(scenario_e)
1 0.000 0.000 2.547 2.547 {built-in method builtins.exec}
5000000 0.851 0.000 0.851 0.000 {built-in method math.modf}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
使用 C/C++ 扩展
我尝试在 C/C++ 支持下编译这两个语句,结果更好。使用 Python 扩展模块可以获得比math.modf 更快、更准确的方法。
math2.pyx:
def modf(number):
cdef float num = <float> number
cdef int i = <int> num
return i, (num*1e17 - i*1e17) / 1e17
test.py:
#!/usr/bin/env python
import math
import cProfile
import math2
""" Get the performance of both statements and math.modf """
X = -100.1323 # The number to be divided into integers and fractions
LOOPS = range(5 * 10 ** 6) # Number of loops
def scenario_a():
""" Tests the speed of the statements in a function using C/C++ support """
for _ in LOOPS:
i, f = math2.modf(X) # (-100, -0.1323)
def scenario_b():
""" Tests the speed of math.modf """
for _ in LOOPS:
f, i = math.modf(X) # (-0.13230000000000075, -100.0)
if __name__ == '__main__':
cProfile.run('scenario_a()')
cProfile.run('scenario_b()')
结果:
5000004 function calls in 1.629 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 1.629 1.629 <string>:1(<module>)
1 1.100 1.100 1.629 1.629 test.py:10(scenario_a)
1 0.000 0.000 1.629 1.629 {built-in method builtins.exec}
5000000 0.529 0.000 0.529 0.000 {math2.modf}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
5000004 function calls in 1.802 seconds
Ordered by: standard name
ncalls tottime percall cumtime percall filename:lineno(function)
1 0.000 0.000 1.802 1.802 <string>:1(<module>)
1 1.010 1.010 1.802 1.802 test.py:16(scenario_b)
1 0.000 0.000 1.802 1.802 {built-in method builtins.exec}
5000000 0.791 0.000 0.791 0.000 {built-in method math.modf}
1 0.000 0.000 0.000 0.000 {method 'disable' of '_lsprof.Profiler' objects}
注意
模数可以使语句更快,但模数不能用于将负数拆分为整数和小数部分。
i, f = int(x), x*1e17%1e17/1e17 # Divide a number (x) into integer and fraction
例如,值100.1323的正值或负值将被划分为:100.1323 -> (100, 0.1323)-100.1323 -> (@ 987654346@, 0.8677)
【讨论】:
此变体允许获得所需的精度:
>>> 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)
【讨论】:
使用math.modf:
import math
x = 1234.5678
math.modf(x) # (0.5678000000000338, 1234.0)
【讨论】:
int_。
modf 操作的逆操作,您只需添加两个部分:1234 + 0.5678 = 1234.5678。你从哪里得到1234 和5678?您的问题似乎与此答案无关。
modf 后问了这个问题。我有 2 个整数:1234 和 5678(不是 0.5678)。所以,可以做到:(1234 - 0.0) + 5678*0.01。由于我必须在数千个这样的数据上运行它,因此正在寻找一些最佳例程(如果存在)。
如果你不介意使用 NumPy,那么:
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)
【讨论】:
这就是我的做法:
num = 123.456
split_num = str(num).split('.')
int_part = int(split_num[0])
decimal_part = int(split_num[1])
【讨论】:
>>> a = 147.234
>>> a % 1
0.23400000000000887
>>> a // 1
147.0
>>>
如果您希望整数部分为整数而不是浮点数,请改用int(a//1)。获取单个段落中的元组:(int(a//1), a%1)
编辑:记住the decimal part of a float number is approximate,所以如果你想像人类一样表示它,你需要使用decimal library
【讨论】:
-2.25 // 1 == -3.0 和 -2.25 % 1 == 0.75。这可能是 OP 想要的,因为 int 部分 + 小数部分仍然等于原始值。相比之下,math.modf(-2.25) == (-0.25, -2.0).
我们可以使用一个不知名的内置函数; divmod:
>>> s = 1234.5678
>>> i, d = divmod(s, 1)
>>> i
1234.0
>>> d
0.5678000000000338
【讨论】:
divmod(-4.5,1) 给出 -5.0 和 0.5。使用 divmod(-4.5, -1) 给出 4.0 和 -0.5。
intpart,decimalpart = int(value),value-int(value)
适用于正数。
【讨论】:
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