Преобразование большой шестнадцатеричной строки в десятичную строку
мне нужно преобразовать большую (слишком большую для встроенных типов данных) шестнадцатеричную строку в строку с ее десятичным представлением. Например:
std::string sHex = "07AA17C660F3DD1D2A1B48F1B746C148";
std::string sDec; // should end up with: "10187768649047767717933300899576725832"
в настоящее время я использую Класс C++ BigInt который предлагает очень простой способ достичь этого (но только GPL):
BigInt::Vin vbiTemp(sHex, 16);
sDec = vbiTemp.toStrDec();
есть ли простой способ сделать это преобразование без сторонней арифметической библиотеки? Или вы можете порекомендовать свободную (не-GPL) альтернативу с подобной простотой (эффективность не имеет значения)?
3 ответов
Ok, вот общий базовый класс конвертера. Я написал оригинальную реализацию на C# и преобразовал ее в C++. Это .NET-происхождение все еще может просвечивать. Не стесняйтесь использовать его, как вы считаете нужным.
вы можете использовать его как это:
const BaseConverter& hex2dec = BaseConverter::HexToDecimalConverter();
std::cout << hex2dec.Convert("07AA17C660F3DD1D2A1B48F1B746C148");
выход будет:
10187768649047767717933300899576725832
класс не ограничивается шестнадцатеричными цифрами, но с радостью переводит между любой базой, используя любую базовую цифру кодирование.
API
-
BaseConverter::BaseConverter(const std::string& sourceBaseSet, const std::string& targetBaseSet);
создает новый экземпляр BaseConverter. Класс переводит между числами, представленными в источник номер базы в цель базовый ряд.
конструктор принимает два строка аргументы для указания символов, которые будут использоваться для исходных и целевых баз чисел. Первый символ в строке имеет значение 0, в 2-й имеет значение 1 и так далее. Пример: символы для восьмеричной базы чисел, как правило,
"01234567"
, а для шестнадцатеричных"0123456789ABCDEF"
. Любой печатаемый символ ASCII может использоваться для символа, поэтому вы можете, например. использовать"OI"
(вместо"01"
) для бинарной системы.Примечание: базовые символы регистр, так что символы
"0123456789abcdef"
будет не декодировать шестнадцатеричные числа с помощью верхнего регистра письмена. -
std::string BaseConverter::Convert(std::string value) const;
std::string BaseConverter::Convert(const std::string& value, size_t minDigits) const;
количество новообращенных
value
в базе исходного номера в базу целевого номера и возвращает результат. 2-я перегрузка принимает дополнительный параметрminDigits
чтобы указать минимальное количество цифр в результате. Возвращаемое значение будет дополнено добавлением нуля или более символов, имеющих значение 0 в целевом номере основа. -
std::string BaseConverter::FromDecimal(unsigned int value) const;
std::string BaseConverter::FromDecimal(unsigned int value, size_t minDigits) const;
преобразование unsigned int десятичное число в целевую базу чисел.
-
unsigned int BaseConverter::ToDecimal(std::string value) const;
преобразует число в исходной системе счисления в десятичное unsigned int. Примечание: результат будет неправильным, если десятичное значение числа в исходной базовой системе превышает UINT_MAX.
-
static const BaseConverter& BaseConverter::DecimalToBinaryConverter();
static const BaseConverter& BaseConverter::BinaryToDecimalConverter();
static const BaseConverter& BaseConverter::DecimalToHexConverter();
static const BaseConverter& BaseConverter::HexToDecimalConverter();
функции удобства, возвращающие экземпляры
BaseConverter
подходит для преобразования между общими базами чисел. Примечание: символы верхнего регистра A-F используются для шестнадцатеричной базы чисел.
BaseConverter.h:
// Arbitrary precision base conversion by Daniel Gehriger <gehriger@linkcad.com>
#include <string>
class BaseConverter
{
public:
std::string GetSourceBaseSet() const { return sourceBaseSet_; }
std::string GetTargetBaseSet() const { return targetBaseSet_; }
unsigned int GetSourceBase() const { return (unsigned int)sourceBaseSet_.length(); }
unsigned int GetTargetBase() const { return (unsigned int)targetBaseSet_.length(); }
/// <summary>
/// Constructor
/// </summary>
/// <param name="sourceBaseSet">Characters used for source base</param>
/// <param name="targetBaseSet">Characters used for target base</param>
BaseConverter(const std::string& sourceBaseSet, const std::string& targetBaseSet);
/// <summary>
/// Get a base converter for decimal to binary numbers
/// </summary>
static const BaseConverter& DecimalToBinaryConverter();
/// <summary>
/// Get a base converter for binary to decimal numbers
/// </summary>
static const BaseConverter& BinaryToDecimalConverter();
/// <summary>
/// Get a base converter for decimal to binary numbers
/// </summary>
static const BaseConverter& DecimalToHexConverter();
/// <summary>
/// Get a base converter for binary to decimal numbers
/// </summary>
static const BaseConverter& HexToDecimalConverter();
/// <summary>
/// Convert a value in the source number base to the target number base.
/// </summary>
/// <param name="value">Value in source number base.</param>
/// <returns>Value in target number base.</returns>
std::string Convert(std::string value) const;
/// <summary>
/// Convert a value in the source number base to the target number base.
/// </summary>
/// <param name="value">Value in source number base.</param>
/// <param name="minDigits">Minimum number of digits for returned value.</param>
/// <returns>Value in target number base.</returns>
std::string Convert(const std::string& value, size_t minDigits) const;
/// <summary>
/// Convert a decimal value to the target base.
/// </summary>
/// <param name="value">Decimal value.</param>
/// <returns>Result in target base.</returns>
std::string FromDecimal(unsigned int value) const;
/// <summary>
/// Convert a decimal value to the target base.
/// </summary>
/// <param name="value">Decimal value.</param>
/// <param name="minDigits">Minimum number of digits for returned value.</param>
/// <returns>Result in target base.</returns>
std::string FromDecimal(unsigned int value, size_t minDigits) const;
/// <summary>
/// Convert value in source base to decimal.
/// </summary>
/// <param name="value">Value in source base.</param>
/// <returns>Decimal value.</returns>
unsigned int ToDecimal(std::string value) const;
private:
/// <summary>
/// Divides x by y, and returns the quotient and remainder.
/// </summary>
/// <param name="baseDigits">Base digits for x and quotient.</param>
/// <param name="x">Numerator expressed in base digits; contains quotient, expressed in base digits, upon return.</param>
/// <param name="y">Denominator</param>
/// <returns>Remainder of x / y.</returns>
static unsigned int divide(const std::string& baseDigits,
std::string& x,
unsigned int y);
static unsigned int base2dec(const std::string& baseDigits,
const std::string& value);
static std::string dec2base(const std::string& baseDigits, unsigned int value);
private:
static const char* binarySet_;
static const char* decimalSet_;
static const char* hexSet_;
std::string sourceBaseSet_;
std::string targetBaseSet_;
};
BaseConverter.cpp:
// Arbitrary precision base conversion by Daniel Gehriger <gehriger@linkcad.com>
#include "BaseConverter.h"
#include <stdexcept>
#include <algorithm>
const char* BaseConverter::binarySet_ = "01";
const char* BaseConverter::decimalSet_ = "0123456789";
const char* BaseConverter::hexSet_ = "0123456789ABCDEF";
BaseConverter::BaseConverter(const std::string& sourceBaseSet, const std::string& targetBaseSet)
: sourceBaseSet_(sourceBaseSet)
, targetBaseSet_(targetBaseSet)
{
if (sourceBaseSet.empty() || targetBaseSet.empty())
throw std::invalid_argument("Invalid base character set");
}
const BaseConverter& BaseConverter::DecimalToBinaryConverter()
{
static const BaseConverter dec2bin(decimalSet_, binarySet_);
return dec2bin;
}
const BaseConverter& BaseConverter::BinaryToDecimalConverter()
{
static const BaseConverter bin2dec(binarySet_, decimalSet_);
return bin2dec;
}
const BaseConverter& BaseConverter::DecimalToHexConverter()
{
static const BaseConverter dec2hex(decimalSet_, hexSet_);
return dec2hex;
}
const BaseConverter& BaseConverter::HexToDecimalConverter()
{
static const BaseConverter hex2dec(hexSet_, decimalSet_);
return hex2dec;
}
std::string BaseConverter::Convert(std::string value) const
{
unsigned int numberBase = GetTargetBase();
std::string result;
do
{
unsigned int remainder = divide(sourceBaseSet_, value, numberBase);
result.push_back(targetBaseSet_[remainder]);
}
while (!value.empty() && !(value.length() == 1 && value[0] == sourceBaseSet_[0]));
std::reverse(result.begin(), result.end());
return result;
}
std::string BaseConverter::Convert(const std::string& value, size_t minDigits) const
{
std::string result = Convert(value);
if (result.length() < minDigits)
return std::string(minDigits - result.length(), targetBaseSet_[0]) + result;
else
return result;
}
std::string BaseConverter::FromDecimal(unsigned int value) const
{
return dec2base(targetBaseSet_, value);
}
std::string BaseConverter::FromDecimal(unsigned int value, size_t minDigits) const
{
std::string result = FromDecimal(value);
if (result.length() < minDigits)
return std::string(minDigits - result.length(), targetBaseSet_[0]) + result;
else
return result;
}
unsigned int BaseConverter::ToDecimal(std::string value) const
{
return base2dec(sourceBaseSet_, value);
}
unsigned int BaseConverter::divide(const std::string& baseDigits, std::string& x, unsigned int y)
{
std::string quotient;
size_t lenght = x.length();
for (size_t i = 0; i < lenght; ++i)
{
size_t j = i + 1 + x.length() - lenght;
if (x.length() < j)
break;
unsigned int value = base2dec(baseDigits, x.substr(0, j));
quotient.push_back(baseDigits[value / y]);
x = dec2base(baseDigits, value % y) + x.substr(j);
}
// calculate remainder
unsigned int remainder = base2dec(baseDigits, x);
// remove leading "zeros" from quotient and store in 'x'
size_t n = quotient.find_first_not_of(baseDigits[0]);
if (n != std::string::npos)
{
x = quotient.substr(n);
}
else
{
x.clear();
}
return remainder;
}
std::string BaseConverter::dec2base(const std::string& baseDigits, unsigned int value)
{
unsigned int numberBase = (unsigned int)baseDigits.length();
std::string result;
do
{
result.push_back(baseDigits[value % numberBase]);
value /= numberBase;
}
while (value > 0);
std::reverse(result.begin(), result.end());
return result;
}
unsigned int BaseConverter::base2dec(const std::string& baseDigits, const std::string& value)
{
unsigned int numberBase = (unsigned int)baseDigits.length();
unsigned int result = 0;
for (size_t i = 0; i < value.length(); ++i)
{
result *= numberBase;
int c = baseDigits.find(value[i]);
if (c == std::string::npos)
throw std::runtime_error("Invalid character");
result += (unsigned int)c;
}
return result;
}
вы можете использовать эту функцию для преобразования шестнадцатеричного символа в десятичный:
void Hex2Char(const char* szHex, unsigned char& rch)
{
rch = 0;
for(int i=0; i<2; i++)
{
if(*(szHex + i) >='0' && *(szHex + i) <= '9')
rch = (rch << 4) + (*(szHex + i) - '0');
else if(*(szHex + i) >='A' && *(szHex + i) <= 'F')
rch = (rch << 4) + (*(szHex + i) - 'A' + 10);
else
break;
}
}
чем вы можете использовать это, чтобы преобразовать строку:
void HexStrToCharStr(const char* hexStr, unsigned char* decStr, int n)
{
unsigned char d_ch;
for(int i=0; i<n; i++)
{
Hex2Char(hexStr+2*i, d_ch);
decStr[i] = d_ch;
}
}