在NumPy中高效迭代,其中下一次迭代取决于前一次的结果。

huangapple go评论64阅读模式
英文:

Iterating efficiently in NumPy where next iteration depends on previous

问题

我正在尝试使用NumPy模拟任意精度的二进制算术。作为一个简单的案例,我有一段代码(在基本的非NumPy Python中),它将一个二进制数加一,其中二进制数被表示为由最不重要位到最重要位的0和1的列表(因此它们从右到左读取为二进制数):

def increment_bits(bits):
    """
    Returns binary representation corresponding to bits + 1
    where bits is a list of 0s and 1s.
    
    >>> increment_bits([1, 1, 1, 0, 1])   # 23 + 1 == 24
    [0, 0, 0, 1, 1]
    >>> increment_bits([1, 1, 1])         #  7 + 1 ==  8   <- an extra bit now needed
    [0, 0, 0, 1]
    """
    new_bits = bits[:]
    for i, v in enumerate(new_bits):
        if v:
            new_bits[i] = 0
        else:
            new_bits[i] = 1
            return new_bits
    # if we have made it here, then there is a final "carry"
    new_bits.append(1)
    return new_bits

我的目标是使用NumPy实现相同的效果,但更快,但我对NumPy还不熟悉,不确定在NumPy数组上迭代以实现所需效果的最快(或最符合NumPy风格)方法。

英文:

I am trying to simulate arbitrary-precision binary arithmetic using NumPy. As a simple case, I have code (in basic, non-NumPy Python) that adds one to a binary number where binary numbers are represented as lists of 0s and 1s from least-to-most significant bits (so they read as binary numbers from right to left):

def increment_bits(bits):
    &quot;&quot;&quot;
    Returns binary representation corresponding to bits + 1
    where bits is a list of 0s and 1s.
    
    &gt;&gt;&gt; increment_bits([1, 1, 1, 0, 1])   # 23 + 1 == 24
    [0, 0, 0, 1, 1]
    &gt;&gt;&gt; increment_bits([1, 1, 1])         #  7 + 1 ==  8   &lt;- an extra bit now needed
    [0, 0, 0, 1]
    &quot;&quot;&quot;
    new_bits = bits[:]
    for i, v in enumerate(new_bits):
        if v:
            new_bits[i] = 0
        else:
            new_bits[i] = 1
            return new_bits
    # if we have made it here, then there is a final &quot;carry&quot;
    new_bits.append(1)
    return new_bits

My goal is to achieve the same effect, but faster, using NumPy, but I am new to NumPy and am not sure the fastest (or most NumPy-onic) way to iterate over a NumPy array to achieve the desired effect.

答案1

得分: 1

I agree with the commenters that Numpy array is not the way to go, but I wanted to give it a try nevertheless. The main idea was to cleverly create a mask for where to add a one by using the cumulative product. This would create an array of 1's until the first 0. We then need to shift by 1 and then set the 0th index to 1 so we add one to every index until after the first 0.

The hope was that maybe numpy had a faster than O(n) implementation of cumulative product, but the result was still slower than just iterating through the list. Also, there's always the overhead of converting to numpy array.

def numpy_bit(bits):
    mask = np.cumprod(bits)
    mask = np.roll(mask, 1)
    mask[0] = 1

    res = (bits + np.ones(len(bits)) * mask) % 2
    if np.all(res == 0):
        return np.append(res, 1)
    else:
        return res
英文:

I agree with the commenters that Numpy array is not the way to go, but I wanted to give it a try nevertheless. The main idea was to cleverly create a mask for where to add a one by using the cumulative product. This would create an array of 1's until the first 0. We then need to shift by 1 and then set the 0th index to 1 so we add one to every index until after the first 0.

The hope was that maybe numpy had a faster than O(n) implementation of cumulative product, but the result was still slower than just iterating through the list. Also, there's always the overhead of converting to numpy array.

def numpy_bit(bits):
    mask = np.cumprod(bits)
    mask = np.roll(mask, 1)
    mask[0] = 1

    res = (bits + np.ones(len(bits)) * mask) % 2
    if np.all(res == 0):
        return np.append(res, 1)
    else:
        return res

huangapple
  • 本文由 发表于 2023年6月30日 03:49:49
  • 转载请务必保留本文链接:https://go.coder-hub.com/76584204.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定