【问题标题】:numpy large integer failednumpy 大整数失败
【发布时间】:2018-12-13 14:13:46
【问题描述】:

我最近在研究一些项目的欧拉问题

最小倍数

问题 5

2520 是可以除以 1 到 10 的每个数字而没有余数的最小数字。

能被 1 到 20 的所有数整除的最小正数是多少?

我写的代码很好用

def factor_finder(n, j=2):

    factor_list = []

    if n == 2:
        return [2]
    elif n == 3:
        return [3]
    else:
        while n >= j * 2:
            while n % j == 0:
                n = int(n / j)
                factor_list.append(j)
            j += 1

    if n > 1:
        factor_list.append(n)

    return factor_list



def smallest_multiples(n):

    from functools import reduce

    factor_list = []
    final_list = []

    for i in range(2, n + 1):
        factor_list += factor_finder(i)
    # print(factor_list)

    for i in set(factor_list):
        l1 = []
        l2 = []
        for j in factor_list:
            if j == i:
                l1.append(j)
            else:
                if len(l1) > len(l2):
                    l2 = l1
                    l1 = []
                else:
                    l1 = []
        # print(l2)
        final_list += l2
    # print(final_list)

    return (
        np.array(final_list).cumprod()[-1],
        reduce((lambda x, y: x * y), final_list),
    )

结果是:

%时间

smallest_multiples(1000)

CPU 时间:用户 5 µs,系统:0 ns,总计:5 µs 挂壁时间:32.4 µs

(-4008056434385126912, 7128865274665093053166384155714272920668358861885893040452001991154324087581111499476444151913871586911717817019575256512980264067621009251465871004305131072686268143200196609974862745937188343705015434452523739745298963145674982128236956232823794011068809262317708861979540791247754558049326475737829923352751796735248042463638051137034331214781746850878453485678021888075373249921995672056932029099390891687487672697950931603520000)

我的问题是为什么 numpy.cumprod() 未能获得正确的数字。我认为 numpy 是非常数字工具。有人可以给我一些想法吗?

【问题讨论】:

    标签: python numpy biginteger


    【解决方案1】:

    问题是数字达到了一个大小,这意味着它不再可以用 Python 中的整数表示。如果您查看here,您会看到整数的最大大小约为 19 位(即 63 位 + 符号位中的 2^63),然后进入溢出状态。 Numpy 基于 C 语言,它使用固定精度来实现更快的计算,但它受到 64 位整数的限制并且会溢出。 numpy 中的一些函数甚至通过转换为浮点数来进行可以容纳更多数字的计算来防止这种情况发生。

    如果你告诉 numpy 使用“object”作为你的数据类型,会有很大的时间损失,但它会让你使用你在 Python 中习惯的任意精度。对于您的代码,它看起来像:

    return (
        np.cumprod(final_list, dtype="object")[-1],
        reduce((lambda x, y: x * y), final_list),
    )
    

    More about overflow in numpy.

    【讨论】:

      【解决方案2】:

      数值分析不是数论。正确性不是唯一的目标,而是必须权衡效率。任意精度的数字(如大整数)很慢,因此 numpy 默认使用固定长度的整数。当它们变得太大时,它们就会溢出。你可以指示 numpy 使用任意精度的整数,但是你会损失很多它的速度:

      np.arange(1, 100).prod() # fast but wrong
      # 0
      np.arange(1, 100, dtype=object).prod() # slow but correct
      # 933262154439441526816992388562667004907159682643816214685929638952175999932299156089414639761565182862536979208272237582511852109168640000000000000000000000
      

      【讨论】:

      • THX,所以 numpy 仍然是数字工具。我现在感觉好多了。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-08-26
      • 2017-02-04
      • 2014-11-02
      • 2021-03-29
      • 1970-01-01
      • 1970-01-01
      • 2018-09-25
      相关资源
      最近更新 更多