【问题标题】:How to split big numbers?如何拆分大数字?
【发布时间】:2010-03-07 22:17:39
【问题描述】:

我有一个大数字,我需要在 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)

但是返回的数字不同。很难调试,因为这个数字太大了,所以在我开始之前,我想我会在这里发布它,看看是否有更好的方法可以做到这一点,或者我是否遗漏了一些明显的东西。

非常感谢。

【问题讨论】:

    标签: python string numbers


    【解决方案1】:

    显然,此操作无法保留“部分”中的任何前导0s。 join_number 不能也接收part_size 参数,以便它可以用所有前导零重构字符串格式吗?

    没有一些信息,例如发送者和接收者都知道的part_size,或等效信息(例如用于基于算术的类似拆分和连接的基数,大致相当于10**part_size 给定的方式你正在使用part_size),任务变得相当困难。如果接收者最初对此一无所知,为什么不将part_size(或base 等)作为arr 正在发送和接收的列表中的第一个int?这样,编码就变得“自给自足”,即不需要发送方和接收方都知道的任何补充参数。

    【讨论】:

    • 啊,当然是前导零。可以将数组中的第一个整数设为 part_size。非常感谢您的帮助,我相信我没有错过。
    【解决方案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
    

    【讨论】:

      【解决方案3】:

      你应该把下面的数字分成 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 了。几乎可以肯定有一种更“Pythonic”的方式来处理那些新奇的 lambda 和事物(或 Python 所称的任何东西),但是,由于您的代码是基本形式,我只是回答了使其工作所需的最小更改.哦,是的,小心负数:-)

      【讨论】:

      • num = '%s%*d' % (num, part_size, int(x))
      【解决方案4】:

      这是 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))
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-11-29
        • 2017-11-04
        • 1970-01-01
        • 2010-09-06
        • 1970-01-01
        • 2013-01-14
        相关资源
        最近更新 更多