C++ 如何将boost::multiprecision::cpp_int转换为&;从一个字节数组

C++ 如何将boost::multiprecision::cpp_int转换为&;从一个字节数组,c++,boost,C++,Boost,我需要两个功能: std::vector<uint8_t> bigint_to_bytes(cpp_int a); cpp_int bytes_to_bigint(std::vector<uint8_t> const& a); std::vector bigint_to_字节(cpp_int a); cpp_int bytes_to_bigint(std::vector const&a); 我在谷歌上搜索发现,bigint到bigint字节可以通过back

我需要两个功能:

std::vector<uint8_t> bigint_to_bytes(cpp_int a); 

cpp_int bytes_to_bigint(std::vector<uint8_t> const& a);
std::vector bigint_to_字节(cpp_int a);
cpp_int bytes_to_bigint(std::vector const&a);
我在谷歌上搜索发现,bigint到bigint字节可以通过
backend().frameds()
实现,不知道如何实现
字节到bigint


如何通过字节数组构造
cpp\u int

我建议采用简单的方法,使用内置后端序列化:

Bytes to_bytes(Bigint const& i) {
    namespace io = boost::iostreams;
    namespace ba = boost::archive;

    std::vector<char> chars;
    {
        io::stream_buffer<io::back_insert_device<Chars> > bb(chars);
        ba::binary_oarchive oa(bb, ba::no_header | ba::no_tracking | ba::no_codecvt);
        oa << i;
    }

    return {chars.begin(), chars.end()};
}
退出,退出代码为0


反过来更容易:改为
vector

boost中的序列化代码如下所示:

template <class Archive, class Int>
void do_serialize(Archive& ar, Int& val, mpl::false_ const&, mpl::false_ const&, mpl::true_ const&)
{
   // Load.
   // Non-trivial.
   // Binary.
   bool s;
   std::size_t c;
   ar & s;
   ar & c;
   val.resize(c, c);
   ar.load_binary(val.limbs(), c * sizeof(limb_type));
   if(s != val.sign())
      val.negate();
   val.normalize();
}

template <class Archive, class Int>
void do_serialize(Archive& ar, Int& val, mpl::true_ const&, mpl::false_ const&, mpl::true_ const&)
{
   // Store.
   // Non-trivial.
   // Binary.
   bool s = val.sign();
   std::size_t c = val.size();
   ar & s;
   ar & c;
   ar.save_binary(val.limbs(), c * sizeof(limb_type));
}

cpp_int_detail::do_serialize(ar, val, save_tag(), trivial_tag(), binary_tag());
namespace {
using BigInt = mp::uint256_t;// boost::multiprecision::cpp_int;

// ignore sign, only support unsigned big integer
// it seems that cpp_int always use big endian
void BigIntToBytes(BigInt const& i, uint8_t* output, size_t len) {

    auto count = i.backend().size();
    auto tsize = sizeof(mp::limb_type);
    auto copy_count = count * tsize;
    if (len < count * tsize)
        throw std::runtime_error("len < count * tsize");
    memcpy(output, i.backend().limbs(), copy_count);
    if (len > copy_count) {
        memset(output + copy_count, 0, len - copy_count);
    }
}

BigInt BytesToBigInt(uint8_t const* output, size_t len) {
    if (len % sizeof(mp::limb_type))
        throw std::runtime_error("len % sizeof(mp::limb_type)");
    BigInt i;
    uint32_t size = (uint32_t)len / sizeof(mp::limb_type);
    i.backend().resize(size, size);
    memcpy(i.backend().limbs(), output, len);
    i.backend().normalize();
    return i;
}
}
模板
void do_serialize(归档&ar,Int&val,mpl::false_u-const&,mpl::false_u-const&,mpl::true_u-const&)
{
//装载。
//不平凡。
//二进制的。
布尔s;
标准:尺寸\u t c;
ar&s;
ar&c;
val.resize(c,c);
ar.load_二进制文件(val.frambs(),c*sizeof(limb_类型));
如果(s!=val.sign())
val.negate();
val.normalize();
}
模板
void do_序列化(归档&ar,Int&val,mpl::true_uu常量&,mpl::false_uu常量&,mpl::true_uu常量&)
{
//商店。
//不平凡。
//二进制的。
布尔s=值符号();
std::size_t c=val.size();
ar&s;
ar&c;
ar.save_二进制文件(val.四肢(),c*sizeof(四肢类型));
}
cpp_int_detail::do_序列化(ar、val、save_tag()、trivity_tag()、binary_tag());
这里有一个关于数字符号的细节

我做了一些测试,发现cpp_int始终使用big-endian,因此即使在某些平台上,例如sizeof(limb_type)==64或==32,我也可以直接使用memcpy,如下所示:

template <class Archive, class Int>
void do_serialize(Archive& ar, Int& val, mpl::false_ const&, mpl::false_ const&, mpl::true_ const&)
{
   // Load.
   // Non-trivial.
   // Binary.
   bool s;
   std::size_t c;
   ar & s;
   ar & c;
   val.resize(c, c);
   ar.load_binary(val.limbs(), c * sizeof(limb_type));
   if(s != val.sign())
      val.negate();
   val.normalize();
}

template <class Archive, class Int>
void do_serialize(Archive& ar, Int& val, mpl::true_ const&, mpl::false_ const&, mpl::true_ const&)
{
   // Store.
   // Non-trivial.
   // Binary.
   bool s = val.sign();
   std::size_t c = val.size();
   ar & s;
   ar & c;
   ar.save_binary(val.limbs(), c * sizeof(limb_type));
}

cpp_int_detail::do_serialize(ar, val, save_tag(), trivial_tag(), binary_tag());
namespace {
using BigInt = mp::uint256_t;// boost::multiprecision::cpp_int;

// ignore sign, only support unsigned big integer
// it seems that cpp_int always use big endian
void BigIntToBytes(BigInt const& i, uint8_t* output, size_t len) {

    auto count = i.backend().size();
    auto tsize = sizeof(mp::limb_type);
    auto copy_count = count * tsize;
    if (len < count * tsize)
        throw std::runtime_error("len < count * tsize");
    memcpy(output, i.backend().limbs(), copy_count);
    if (len > copy_count) {
        memset(output + copy_count, 0, len - copy_count);
    }
}

BigInt BytesToBigInt(uint8_t const* output, size_t len) {
    if (len % sizeof(mp::limb_type))
        throw std::runtime_error("len % sizeof(mp::limb_type)");
    BigInt i;
    uint32_t size = (uint32_t)len / sizeof(mp::limb_type);
    i.backend().resize(size, size);
    memcpy(i.backend().limbs(), output, len);
    i.backend().normalize();
    return i;
}
}
名称空间{
使用BigInt=mp::uint256\u t;//boost::multiprecision::cpp\u int;
//忽略符号,仅支持无符号大整数
//cpp_int似乎总是使用big-endian
void BigIntToBytes(BigInt const&i、uint8\u t*输出、大小长度){
自动计数=i.backend().size();
自动tsize=sizeof(mp::肢体类型);
自动复制\u计数=计数*t大小;
如果(长度<计数*t大小)
抛出std::运行时错误(“len复制计数){
memset(输出+拷贝计数,0,len-拷贝计数);
}
}
BigInt BytesToBigInt(uint8常量*输出,大小长度){
if(长度%sizeof(mp::肢_型))
抛出std::runtime_错误(“len%sizeof(mp::limb_类型)”;
比金特一号;
uint32_t size=(uint32_t)len/sizeof(mp::limb_type);
i、 backend().resize(大小、大小);
memcpy(i.后端().肢体(),输出,len);
i、 后端().normalize();
返回i;
}
}

非常感谢!奇怪的是:to_字节(uint256_值)。size()是51,前面似乎有一个19字节的头。ba::no_头似乎不起作用。在我的x86-64 Windows机器上,使用VS2017编译的Boost 1.69.0,cpp_int似乎存储在little endian中。您使用的是哪种体系结构和编译器?