C / C ++位阵列分辨率转换算法

时间:2018-10-03 23:16:40

标签: c++ c arrays loops bitset

有人知道上/下转换位数组的任何算法吗?

即:当分辨率为1/16时:

每1位= 16位。 (从低分辨率到高分辨率)

create_table "sites", force: :cascade do |t|
    t.bigint "location_id"
    t.string "review_site"
    t.string "direct_review_url"
    t.string "place_id"
    t.decimal "average_rating"
    t.jsonb "extra_data", default: {}, null: false
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.integer "rating_count"
    t.index ["extra_data"], name: "index_sites_on_extra_data", using: :gin
    t.index ["location_id"], name: "index_sites_on_location_id"
  end
create_table "available_sites", force: :cascade do |t|
    t.string "name"
    t.string "link_to_info"
    t.string "link_to_signup"
    t.string "base_review_url"
    t.datetime "created_at", null: false
    t.datetime "updated_at", null: false
    t.index ["name"], name: "index_available_sites_on_name"
  end

反之,16位= 1位(高分辨率到低分辨率)

1010 -> 1111111111111111000000000000000011111111111111110000000000000000

现在我正在一点一点地循环,效率不高。使用整个64位字会更好,但是当无法通过分辨率将其均分时会遇到问题(某些位可能会溢出到下一个字)。

C ++:

1111111111111111000000000000000011111111111111110000000000000000 -> 1010

C:

std::vector<uint64_t> bitset; 

可通过以下方式访问:

uint64_t *bitset = calloc(total_bits >> 6, sizeof(uint64_t)); // free() when done

并设置/清除:

const uint64_t idx = bit >> 6;
const uint64_t pos = bit % 64;

const bool value = (bitset[idx] >> pos) & 1U;

和具有相同分辨率的两个位集的OR(或AND / XOR / AND / NOT)是使用完整的64位字完成的:

bitset[idx] |= (1UL << pos);
bitset[idx] &= ~(1UL << pos);

我正在处理足够大的位集(2+十亿位),因此我正在寻找循环中的任何效率。我发现优化循环的一种方法是使用bitset[idx] |= source.bitset[idx]; 检查每个单词,然后在循环中跳过:

__builtin_popcountll

我在寻找算法/技术而不是代码示例。但是,如果您有共享的代码,我不会拒绝。任何学术研究论文也将不胜感激。

谢谢!

1 个答案:

答案 0 :(得分:0)

分辨率是否始终在1/2到1/64之间?甚至是1/32?因为如果需要很长的序列,则可能需要更多的循环嵌套,这可能会导致速度变慢。

您的序列是否总是很长(数百万位),或者这是最大值,但是通常您的序列较短?从高分辨率到低分辨率时,可以假定数据有效还是无效。

以下是一些技巧:

.card {
    margin-left: 30px;
    margin-right: 30px;
    width: auto;
    border-radius: 8px;

    position: relative;
    // height: 150px;
    display: block;
    margin-top: 350px; /* changed */
    overflow: visible;

    div {
        position: absolute;
        top: -95px;
        width: 100%;
        // z-index: 2;
        text-align: center;
    }


    img:not(.castImg) {
        width: 50%; /* changed */
        // margin: auto;
        border-radius: 8px;

        -webkit-box-shadow: 0 8px 6px -6px black;
        -moz-box-shadow: 0 8px 6px -6px black;
        box-shadow: 0 8px 6px -6px black;


        display: block;
        // width: 128px;
        // height: 128px;
        // margin: 30px auto 0;
        margin: -200px auto 0; /* changed */
    }
}

如果您的序列太长,则可能需要检查uint64_t one = 1; uint64_t n_one_bits = (one << n) - 1u; // valid for 0 to 63; not sure for 64 是否为2的幂并针对这些情况具有更优化的代码。

您可能会在这里找到其他有用的技巧:

https://graphics.stanford.edu/~seander/bithacks.html

因此,如果您的分辨率为1/16,则不需要循环单个16位,但是可以一次检查所有16位。然后,您可以一次又一次地重复下一个小组。

如果数字不是64的除数,则每次越过64位边界时,都可以适当地移位位。假设您的分辨率为1/5,那么您可以处理60位,然后将剩余的4位移位并与随后的60位合并。

如果您可以假定数据有效,那么您甚至不需要移动原始数字,因为您每次都可以选择适当的位的值。