将74位整数转换为基数31

Thi*_* B. 6 c++ base-conversion bigint c++11 std-bitset

要生成UFI编号,我使用bitset大小为74.要执行UFI生成的第2步,我需要转换此数字:

9 444 732 987 799 592 368 290
(10000000000000000000000000000101000001000001010000011101011111100010100010)
Run Code Online (Sandbox Code Playgroud)

成:

DFSTTM62QN6DTV1
Run Code Online (Sandbox Code Playgroud)

通过将第一个表示转换为基数31并从表中获取等效的字符.

#define PAYLOAD_SIZE 74
// payload = binary of 9444732987799592368290
std::bitset<PAYLOAD_SIZE> bs_payload(payload);
/*
perform modulo 31 to obtain:
12(D), 14(F), 24(S), 25(T), 25, 19, 6, 2, 22, 20, 6, 12, 25, 27, 1
*/    
Run Code Online (Sandbox Code Playgroud)

有没有办法在不使用外部BigInteger库的情况下对我的bitset执行转换?

编辑:BigInteger即使是干杯和赫斯,我终于完成了一堂课.- 阿尔夫的解决方案就像一个魅力

Che*_*Alf 1

这段代码似乎有效。为了保证结果,我认为你需要做额外的测试。例如,首先使用小数字,您可以直接计算结果。

编辑:哦,现在我注意到您发布了所需的结果数字,并且它们匹配。意味着它总体上是好的,但仍未针对极端情况进行测试。

#include <assert.h>
#include <algorithm>            // std::reverse
#include <bitset>
#include <vector>
#include <iostream>
using namespace std;

template< class Type > using ref_ = Type&;

namespace base31
{
    void mul2( ref_<vector<int>> digits )
    {
        int carry = 0;
        for( ref_<int> d : digits )
        {
            const int local_sum = 2*d + carry;
            d = local_sum % 31;
            carry = local_sum / 31;
        }
        if( carry != 0 )
        {
            digits.push_back( carry );
        }
    }

    void add1( ref_<vector<int>> digits )
    {
        int carry = 1;
        for( ref_<int> d : digits )
        {
            const int local_sum = d + carry;
            d = local_sum % 31;
            carry = local_sum / 31;
        }
        if( carry != 0 )
        {
            digits.push_back( carry );
        }
    }

    void divmod2( ref_<vector<int>> digits, ref_<int> mod )
    {
        int carry = 0;
        for( int i = int( digits.size() ) - 1; i >= 0; --i )
        {
            ref_<int> d = digits[i];
            const int divisor = d + 31*carry;
            carry = divisor % 2;
            d = divisor/2;
        }
        mod = carry;
        if( digits.size() > 0 and digits.back() == 0 )
        {
            digits.resize( digits.size() - 1 );
        }
    }
}


int main() {
    bitset<74> bits(
        "10000000000000000000000000000101000001000001010000011101011111100010100010"
        );
    vector<int> reversed_binary;
    for( const char ch : bits.to_string() ) { reversed_binary.push_back( ch - '0' ); }

    vector<int> base31;
    for( const int bit : reversed_binary )
    {
        base31::mul2( base31 );
        if( bit != 0 )
        {
            base31::add1( base31 );
        }
    }

    { // Check the conversion to base31 by converting back to base 2, roundtrip:
        vector<int> temp31 = base31;
        int mod;
        vector<int> base2;
        while( temp31.size() > 0 )
        {
            base31::divmod2( temp31, mod );
            base2.push_back( mod );
        }
        reverse( base2.begin(), base2.end() );
        cout << "Original     : " << bits.to_string() << endl;
        cout << "Reconstituted: ";
        string s;
        for( const int bit : base2 ) { s += bit + '0'; cout << bit; };  cout << endl;
        assert( s == bits.to_string() );
    }

    cout << "Base 31 digits (msd to lsd order): ";
    for( int i = int( base31.size() ) - 1; i >= 0; --i )
    {
        cout << base31[i] << ' ';
    }
    cout << endl;

    cout << "Mod 31 = " << base31[0] << endl;
}
Run Code Online (Sandbox Code Playgroud)

MinGW g++ 的结果:

原件:10000000000000000000000000000101000001000001010000011101011111100010100010
重构:10000000000000000000000000000101000001000001010000011101011111100010100010
31 位基数(msd 到 lsd 顺序):12 14 24 25 25 19 6 2 22 20 6 12 25 27 1
模 31 = 1


归档时间:

查看次数:

578 次

最近记录:

7 年,8 月 前