2010-03-07 37 views
0

我有一个很大的数字,我需要在Python中分割成更小的数字。我写了下面的代码在两者之间进行交换:如何分割大数字?


def split_number (num, part_size): 
    string = str(num) 
    string_size = len(string) 

    arr = [] 
    pointer = 0 
    while pointer < string_size: 
     e = pointer + part_size 
     arr.append(int(string[pointer:e])) 
     pointer += part_size 
    return arr 

def join_number(arr): 
    num = "" 
    for x in arr: 
     num += str(x) 
    return int(num) 

但是数字会有所不同。这很难调试,因为数量太大了,所以在我进入之前,我想我会在这里发布它,看看是否有更好的方法来做到这一点,或者我是否错过了明显的东西。

非常感谢。

+3

每个块中的前导零? – 2010-03-07 01:00:01

回答

2

很明显,任何领先的0 s在“部分”不能通过此操作保留。不能join_number也收到part_size参数,以便它可以重建与所有前导零的字符串格式?

没有一些信息,比如part_size是上已知的发送端两者和接收器,或同等学历(如基数使用了类似的分裂和加入基于算法,​​大致相当于10**part_size给你的方式使用part_size),任务变得相当困难。如果接收机最初对此无能为力,为什么不把part_size(或基地等)作为发送和接收的arr列表中的第一个int?这样,编码变得“自给自足”,即不需要发送者和接收者都知道的任何补充参数。

+0

啊,当然是领先零。可以使数组中的第一个整数为part_size。 非常感谢您的帮助,我不相信我错过了这一点。 – Reality 2010-03-07 01:09:02

1

你应该考虑以下一些分成3个大小的块:

1000005 -> 100 000 5 

你有两个问题。第一个是,如果你把这些整数重新走到一起,你会得到:

100 0 5 -> 100005 

(即中间的一个是0,而不是000),这是不是你开始用什么。第二个问题是你不确定最后一部分应该是多大。

我会确保你第一次使用其长度的字符串零件尺寸的整数倍,所以你知道确切如何大每个部分应该是:

def split_number (num, part_size): 
    string = str(num) 
    string_size = len(string) 
    while string_size % part_size != 0: 
     string = "0%s"%(string) 
     string_size = string_size + 1 

    arr = [] 
    pointer = 0 
    while pointer < string_size: 
     e = pointer + part_size 
     arr.append(int(string[pointer:e])) 
     pointer += part_size 
    return arr 

其次,确保你把后面的部分连同合适的长度为每个部分(确保你不把前导零对课程的第一部分):

def join_number(arr, part_size): 
    fmt_str = "%%s%%0%dd"%(part_size) 
    num = arr[0] 
    for x in arr[1:]: 
     num = fmt_str%(num,int(x)) 
    return int(num) 

尝试所有这些,下面的完整的程序:

#!/usr/bin/python 

def split_number (num, part_size): 
    string = str(num) 
    string_size = len(string) 
    while string_size % part_size != 0: 
     string = "0%s"%(string) 
     string_size = string_size + 1 

    arr = [] 
    pointer = 0 
    while pointer < string_size: 
     e = pointer + part_size 
     arr.append(int(string[pointer:e])) 
     pointer += part_size 
    return arr 

def join_number(arr, part_size): 
    fmt_str = "%%s%%0%dd"%(part_size) 
    num = arr[0] 
    for x in arr[1:]: 
     num = fmt_str%(num,int(x)) 
    return int(num) 

x = 1000005 
print x 
y = split_number(x,3) 
print y 
z = join_number(y,3) 
print z 

产生输出:

1000005 
[1, 0, 5] 
1000005 

这表明它可以追溯到在一起。

请记住,我几年没有完成Python。几乎可以肯定的是,使用这些新开发的lambda表达式和其他东西(或者任何Python称为它们)的方法会有更多的“Pythonic”方法,但是,由于代码是基本形式,因此我只是回答了需要进行的最小更改才能使其运行。噢,并警惕负数:-)

+0

num =''%s%* d'%(num,part_size,int(x))' – 2010-03-07 14:23:13

2

无需转换和从字符串,它可以是非常耗时的真正大量

>>> def split_number(n, part_size): 
...  base = 10**part_size 
...  L = [] 
...  while n: 
...   n,part = divmod(n,base) 
...   L.append(part) 
...  return L[::-1] 
... 
>>> def join_number(L, part_size): 
...  base = 10**part_size 
...  n = 0 
...  L = L[::-1] 
...  while L: 
...   n = n*base+L.pop() 
...  return n 
... 
>>> print split_number(1000005,3) 
[1, 0, 5] 
>>> print join_number([1,0,5],3) 
1000005 
>>> 

在这里你可以看到,刚将数字转换为str需要比我的整个功能更长的时间!

>>> from time import time 
>>> t=time();b = split_number(2**100000,3000);print time()-t 
0.204252004623 
>>> t=time();b = split_number(2**100000,30);print time()-t 
0.486856222153  
>>> t=time();b = str(2**100000);print time()-t 
0.730905056 
0

这是Alex Martelli的答案的一些代码。

def digits(n, base): 
    while n: 
     yield n % base 
     n //= base 

def split_number(n, part_size): 
    base = 10 ** part_size 
    return list(digits(n, base)) 

def join_number(digits, part_size): 
    base = 10 ** part_size 
    return sum(d * (base ** i) for i, d in enumerate(digits))