基本上我正在尝试做的是用C ++创建一个基数为62的数字系统(一个字母数字系统 - 一个包含a-z,A-Z和0-9的系统)。如何完成这样的事情?我尝试使用这样的char数组:
const char alphaNum[62] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', ' y', 'z', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
然而编写函数来使用该数组并尝试计数需要太多代码才能实用(对于0到61,当然,只需从数组中选择它。当您尝试执行多位数时出现问题,即00)。简单地说foobar++;
会简单得多。有没有人有办法定义数字系统,或者至少有一种方法让我这样做,这样我每次到达Z时都不必写一个案例?
答案 0 :(得分:8)
您需要将外部(用户)表示和内部表示分开。
内部代表
在计算机内部,您应该使用最有效的表示。这可以是十六进制,二进制或十进制;或者不要担心。
向用户展示时,您应使用外部表示。
外部代表
您的角色数组代表您的号码系统的位数。 (它也应该是const
。)您需要从内部表示中隔离数字。例如,在基数16中,我们将数字除以16以将数字向右移动并使用 modulo 除以得到余数。余数是数字值。使用余数来查找数组中的数字表示。
在较小的数字基础上尝试您的算法,例如17或18.扩展到基数62应该是更改#define
或const integer
。
编辑1:困难的方法
更难的方法是为数字系统的每个数字使用一个字节。字节,八位字节或无符号字符的范围为0到255,因此应该容纳一个数字的基数62.
使用std::vector<unsigned char>
代表您的电话号码。您必须确定最重要的数字是在向量的前面还是在末尾。
增加数字:
add 1 to digit.
if digit value > 62
{
set digit to zero.
Load digit with next greater column value (i.e. vector[position + 1];
Repeat at top of algorithm
}
这是标准算法,无论基数(10,8,16等)如何 十进制加法,减法,乘法和除法的基本规则仍然适用。 (提示)。
这是 Big Number 库中使用的一种技术。
答案 1 :(得分:4)
以下可能有所帮助:(http://ideone.com/y1gZDF) (您可以更改内部表示以适合您的需要,作为 BigNumber )。
class N62
{
public:
explicit N62(const std::string& digits) : N62(digits.c_str(), digits.size()) {}
N62(const char* digits, std::size_t len) : value(0u)
{
for (std::size_t i = 0; i != len; ++i) {
auto pos = std::find(std::begin(base), std::end(base), digits[i]);
if (pos == std::end(base)) {
throw std::runtime_error("incorrect digit");
}
value *= 62;
value += pos - std::begin(base);
}
}
N62(std::size_t value) : value(value) {}
operator std::size_t () const { return value; }
std::string str() const
{
if (value == 0u) {
return "0";
}
std::string res;
for (std::size_t n = value; n != 0; n /= 62) {
res.push_back(base[n % 62]);
}
std::reverse(res.begin(), res.end());
return res;
}
private:
std::size_t value;
private:
static constexpr char base[] =
"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
};
此外,您可以添加用户字符串文字,如下所示:
N62 operator "" _n62 (const char *t, std::size_t len)
{
return N62(t, len);
}
并以这种方式使用:"1Z"_n62
(在123
中以小数形式解析)。
答案 2 :(得分:1)
数字系统只是数字的表示。数字并不介意我们如何编写它们。所以,我们的问题是:
如何使用base62在程序文本中声明数字?
您应该声明如何标记base62号码。 &#34; 0X&#34;和&#34; $&#34;前缀保留给base16,&#34; 0&#34;前缀保留给八进制,&#34;%&#34;二进制的前缀,&#34; *&#34;可能有几个原因使用tilde是你的前缀,例如:~Uu3n
然后,您应该编写一个预处理器,它将您的base62数字转换为十进制(或十六进制,如您所愿)格式。
如何在base62中输出数字?
这更难。您应该将所有数字输出转换为base62。所以
printf("%d in base62 is %D \n",value,value);
应转换为
printf("%d in base62 is %s \n",value,tob64(value));
不太优雅。
也许包装类应该更好(比如Java中的 Integer )。