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中。您使用的是哪种体系结构和编译器?