我想在C ++中添加2个任意大小的整数。我怎么能这样做呢?
答案 0 :(得分:15)
这是一个示例,说明如何将OpenSSL bignum实现用于任意精度算术。我的例子是2 64 + 2 65 。我正在使用Linux。
#include <cstdio>
#include <openssl/crypto.h>
#include <openssl/bn.h>
int main(int argc, char *argv[])
{
static const char num1[] = "18446744073709551616";
static const char num2[] = "36893488147419103232";
BIGNUM *bn1 = NULL;
BIGNUM *bn2 = NULL;
BN_CTX *ctx = BN_CTX_new();
BN_dec2bn(&bn1, num1); // convert the string to BIGNUM
BN_dec2bn(&bn2, num2);
BN_add(bn1, bn1, bn2); // bn1 = bn1 + bn2
char *result_str = BN_bn2dec(bn1); // convert the BIGNUM back to string
printf("%s + %s = %s\n", num1, num2, result_str);
OPENSSL_free(result_str);
BN_free(bn1);
BN_free(bn2);
BN_CTX_free(ctx);
return 0;
}
它产生这个输出:
18446744073709551616 + 36893488147419103232 = 55340232221128654848
您需要在开发库中安装OpenSSL。如果您有Linux,请从软件包管理器安装开发库,并链接到libcrypto.so
。
g++ bignum.cpp -o bignum -lcrypto
或下载OpenSSL源代码并构建静态库libcrypto.a
并静态链接。
g++ bignum.cpp -o bignum -I./openssl-1.0.0/include ./openssl-1.0.0/libcrypto.a
在Windows上,您需要从OpenSSL的Windows port安装。
答案 1 :(得分:4)
使用+
运算符?
答案 2 :(得分:4)
我想在C ++中添加2个任意大小的整数。我怎么能这样做呢?
如果你想自己进行多精度数学运算,那么我建议你看看Donald Knuth的Art of Computer Programming。我相信第二卷,精神数学算法,第四章,多精度算术,是你感兴趣的.Knuth给你所有的血腥细节。
Handling large numbers in C++?也提供了一篇有趣的论文。如果您正在编写自己的实现,则应该阅读它。 (其他类似的问题缺乏参考。感谢@herohuyongtao提供它。)
除了在C中使用OpenSSL的@indiv答案外,您还可以使用Botan或Crypto++。两者都是C ++库,两者都和OpenSSL一样大。考虑到您的问题被标记为C ++,我很惊讶没有为他们提供答案。
如果你有C ++ 11或unique_ptr
,那么你可以将它们用于OpenSSL C代码。 unique_ptr
真的整理了一切。下面给出一个例子。
以下是该计划:
$ cat test.cxx
#include "botan/bigint.h"
#include <iostream>
int main()
{
using Botan::BigInt;
BigInt num1("18446744073709551616");
BigInt num2("36893488147419103232");
std::cout << num1 + num2 << std::endl;
std::cout << std::hex << "0x" << num1 + num2 << std::endl;
return 0;
}
从图书馆目录建立(权宜之计):
$ g++ -I ./build/include test.cxx ./libbotan-2.a -o test.exe
$ ./test.exe
55340232221128654848
0x30000000000000000
以下是该计划:
$ cat test.cxx
#include "cryptlib.h"
#include "integer.h"
#include <iostream>
int main()
{
using CryptoPP::Integer;
Integer num1("18446744073709551616");
Integer num2("36893488147419103232");
std::cout << num1 + num2 << std::endl;
std::cout << std::hex << "0x" << num1 + num2 << std::endl;
return 0;
}
从图书馆目录建立(权宜之计):
$ g++ -I . test.cxx ./libcryptopp.a -o test.exe
$ ./test.exe
55340232221128654848.
0x30000000000000000h
这是C ++和OpenSSL的程序。 BN_obj
“包含”BIGNUM
,并使用unique_ptr
来管理资源。
$ cat test.cxx
#include "openssl/bn.h"
#include "openssl/err.h"
#include <iostream>
#include <stdexcept>
#include <sstream>
#include <memory>
#include <new>
class BN_obj
{
using BN_ptr = std::unique_ptr<BIGNUM, decltype(&::BN_free)>;
using BN_CTX_ptr = std::unique_ptr<BN_CTX, decltype(&::BN_CTX_free)>;
public:
BN_obj() : m_bn(BN_Zero_Helper(), ::BN_free) {}
BN_obj(const char* str) : m_bn(BN_Asciiz_Helper(str), ::BN_free) {}
BN_obj(const BN_obj& obj) : m_bn(BN_Copy_Helper(obj.m_bn), ::BN_free) {}
BN_obj& operator=(const BN_obj& obj)
{
if(this != &obj)
m_bn.reset(BN_dup(obj.m_bn.get()));
return *this;
}
BN_obj Plus(const BN_obj& obj) const
{
BN_obj result;
if (BN_add(result.m_bn.get(), m_bn.get(), obj.m_bn.get()) != 1)
{
std::ostringstream msg;
unsigned long err = ERR_get_error();
msg << "BN_add failed, error 0x" << std::hex << err;
throw std::runtime_error(msg.str());
}
return result;
}
BN_obj Minus(const BN_obj& obj) const
{
BN_obj result;
if (BN_sub(result.m_bn.get(), m_bn.get(), obj.m_bn.get()) != 1)
{
std::ostringstream msg;
unsigned long err = ERR_get_error();
msg << "BN_sub failed, error 0x" << std::hex << err;
throw std::runtime_error(msg.str());
}
return result;
}
BN_obj Times(const BN_obj& obj) const
{
BN_obj result;
BN_CTX_ptr ctx(BN_CTX_new(), ::BN_CTX_free);
if (BN_mul(result.m_bn.get(), m_bn.get(), obj.m_bn.get(), ctx.get()) != 1)
{
std::ostringstream msg;
unsigned long err = ERR_get_error();
msg << "BN_sub failed, error 0x" << std::hex << err;
throw std::runtime_error(msg.str());
}
return result;
}
friend std::ostream& operator<<(std::ostream& out, const BN_obj& obj);
protected:
static BIGNUM* BN_Zero_Helper()
{
BIGNUM* z = BN_new();
BN_zero(z);
return z;
}
static BIGNUM* BN_Asciiz_Helper(const char* str)
{
BIGNUM* t = BN_new();
if(!t)
throw std::bad_alloc();
if(BN_dec2bn(&t, str) == 0) {
std::ostringstream msg;
unsigned long err = ERR_get_error();
msg << "BN_dec2bn failed, error 0x" << std::hex << err;
throw std::runtime_error(msg.str());
}
return t;
}
static BIGNUM* BN_Copy_Helper(const BN_ptr& obj)
{
return BN_dup(obj.get());
}
private:
BN_ptr m_bn;
};
BN_obj operator+(const BN_obj& a, const BN_obj& b) {
return a.Plus(b);
}
BN_obj operator-(const BN_obj& a, const BN_obj& b) {
return a.Minus(b);
}
BN_obj operator*(const BN_obj& a, const BN_obj& b) {
return a.Times(b);
}
std::ostream& operator<<(std::ostream& out, const BN_obj& obj)
{
const long f = out.flags() & std::ios::basefield;
char* ptr = nullptr;
if(f == std::ios::hex)
{
ptr = BN_bn2hex(obj.m_bn.get());
out << ptr;
}
else if(f == std::ios::dec)
{
ptr = BN_bn2dec(obj.m_bn.get());
out << ptr;
}
else
throw std::runtime_error("Not implemented");
if(ptr)
OPENSSL_free(ptr);
return out;
}
int main()
{
const char z1[] = "18446744073709551616";
const char z2[] = "36893488147419103232";
BN_obj num1(z1);
BN_obj num2(z2);
std::cout << num1 + num2 << std::endl;
std::cout << std::hex << "0x" << num1 + num2 << std::endl;
return 0;
}
从图书馆目录建立(权宜之计):
$ g++ -I ./include test.cxx ./libcrypto.a -o test.exe -ldl -pthread
$ ./test.exe
55340232221128654848
0x30000000000000000