简体   繁体   中英

Python Bit Summation Algorithm

I am trying to implement a function that will be used to judge whether a generator's output is continuous. The method I am gravitating towards is to iterate through the generator. For each value, I right justify the bits of the value (disregarding the 0b ), count the number of ones, and shift the number of ones.

#!/usr/bin/python3
from typing import Tuple


def find_bit_sum(top: int, pad_length: int) -> int :
    """."""
    return pad_length * (top + 1)


def find_pad_length(top: int) -> int :
    """."""
    return len(bin(top)) - 2  # -"0b"


def guess_certain(top: int, pad_length: int) -> Tuple[int, int, int] :
    """."""
    _both: int = find_bit_sum(top, pad_length)
    _ones: int = sum(sum(int(_i_in) for _i_in in bin(_i_out)[2 :]) for _i_out in range(1, top + 1))
    return _both - _ones, _ones, _both  # zeros, ones, sum


def guess(top: int, pad_length: int) -> Tuple[int, int, int] :  # zeros then ones then sum
    """."""
    _bit_sum: int = find_bit_sum(top, pad_length)  # number of bits in total
    _zeros: int = _bit_sum  # ones are deducted
    _ones: int = 0  # _bit_sum - _zeros
    # detect ones
    for _indexed in range(pad_length) :
        _ones_found: int = int(top // (2 ** (_indexed + 1)))  # HELP!!!
        _zeros -= _ones_found
        _ones += _ones_found
    #
    return _zeros, _ones, _bit_sum


def test_the_guess(max_value: int) -> bool :  # the range is int [0, max_value + 1)
    pad: int = find_pad_length(max_value)
    _zeros0, _ones0, _total0 = guess_certain(max_value, pad)
    _zeros1, _ones1, _total1 = guess(max_value, pad)
    return all((
        _zeros0 == _zeros1,
        _ones0 == _ones1,
        _total0 == _total1
    ))


if __name__ == '__main__' :  # should produce a lot of True
    for x in range(3000) :
        print(test_the_guess(x))

For the life of me, I cannot make guess() agree with guess_certain() . The time complexity of guess_certain() is my problem: it works for small ranges [0, top] , but one can forget 256-bit numbers ( top s). The find_bit_sum() function works perfectly. The find_pad_length() function also works.

top // (2 ** (_indexed + 1))

I've tried 40 or 50 variations of the guess() function. It has thoroughly frustrated me. The guess() function is probabilistic. In its finished state: if it returns False , then the Generator definitely isn't producing every value in range(top + 1) ; however, if it returns True , then the Generator could be. We already know that the generator range(top + 1) is continuous because it does produce each number between 0 and top inclusively; so, test_the_guess() should be returning True .

I sincerely do apologise for the chaotic explanation. If you have anny questions, please don't hesitate to ask.

I adjusted your ones_found assignment statement to account for the number of powers of two per int(top // (2 ** (_indexed + 1))) , as well as a additional "rollover" ones that occur before the next power of two. Here is the resulting statement:

_ones_found: int = int(top // (2 ** (_indexed + 1))) * (2 ** (_indexed)) + max(0, (top % (2 ** (_indexed + 1))) - (2 ** _indexed) + 1)

I also took the liberty of converting the statement to bitwise operators for both clarity and speed, as shown below:

_ones_found: int = ((top >> _indexed + 1) << _indexed) + max(0, (top & (1 << _indexed + 1) - 1) - (1 << _indexed) + 1)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM