将数字的八进制表示形式转换为十进制

时间:2011-08-21 12:11:58

标签: c++ hex

假设一个具有N个元素的向量或数组(N可以非常大),其包含非负整数的八进制表示。如何从此数组中获取数字的十进制表示?代码必须非常快。

编辑:N个元素的数组A包含非负整数K的八进制表示,即A的每个元素属于区间[0; 7](包括两端)

示例:A [0] = 2; A [1] = 6; A [2] = 3

现在天真的计算是2 * 8pow0 + 6 * 8pow1 + 3 * 8pow2 = 2 + 48+ 192 = 242

我尝试了这个,但它似乎不适用于大输入> 6K

//vector<int> A is the input
using namespace std;
vector<int>::iterator it = A.begin();

unsigned int k = 0;
unsigned int x = 0;
while(it < A.end()){
   x = x | (*it<<3*k);
   k++;
   it++;
}

我在将十六进制字符串转换为十进制表示时遇到问题?这是在C ++中执行此操作的正确方法: //假设S是包含十六进制表示的输入字符串 //喜欢F23

std::stringstream ss;
ss << std::hex << S;
ss >> x;

2 个答案:

答案 0 :(得分:2)

Arbitray精度八进制到十进制转换相当烦人,因为没有办法本地化计算。换句话说,八进制数字的最高有效数字的变化将改变十进制表示中的最低有效数字。

那说我想我会把八进制数转换成一个基数为1000000000的数字,然后我打印出来(这是一个微不足道的问题,每个基数为1000000000的数字只是简单地映射到9个基数为10的数字)

转换为base-1000000000非常简单,因为您只需要支持递增和乘以2(只需将输入视为二进制,每个八进制数位为三位)。

修改

我试图用C ++实现它,这是生成的代码

#include <stdio.h>
#include <vector>

int main(int argc, const char *argv[]) {
    // Base 100,000,000 accumulator
    // Initialized with one digit = 0
    std::vector<unsigned> big(1);
    const unsigned DIGIT = 100000000;

    for (int c=getchar(); c >= '0' && c <= '7'; c=getchar()) {
        // Multiply accumulator by 8 and add in incoming digit
        int carry = c - '0';
        for (int i=0,n=big.size(); i<n; i++) {
            unsigned x = big[i] * 8 + carry;
            carry = x / DIGIT;
            big[i] = x - carry * DIGIT;
        }
        if (carry) big.push_back(carry);
    }

    // Output result in decimal
    printf("%i", big.back());
    for (int i=int(big.size())-2; i>=0; i--) {
        printf("%08i", big[i]);
    }
    putchar('\n');
    return 0;
}

在我的电脑上,将80,000位八进制数转换为十进制数(产生72246位数)的时间约为1.2秒。使用python eval / str执行相同操作的时间约为3秒。使用的数字是"01234567" * 10000

上面的代码使用100,000,000作为基础,因此它可以一次处理一个数字(3位),32位算术不会溢出中间结果。我也尝试使用64位整数或double的53位整数部分,但代码运行总是慢于这种情况(一个原因可能是内循环中可以转换为乘法的除法32位情况。)

这仍然是一个简单的O(n ^ 2)实现,需要很长时间来转换10,000,000位的八进制数。

答案 1 :(得分:1)

这就是我提出的:

template<typename Iter>
int read_octal(Iter begin, Iter end)
{
    int x = 0;
    int f = 1;
    for (; begin != end; ++begin)
    {
        x += *begin * f;
        f *= 8;
    }
    return x;
}

int main()
{
    int test[] = {2, 6, 3};
    int result = read_octal(test + 0, test + 3);
    std::cout << result << '\n';
}
  

我尝试了这个,但它似乎不适用于大输入&gt; 6K

6k究竟是什么意思? int通常具有32位,八进制数字具有3位。因此,您的范围内不能超过10个元素,否则x将溢出。

  

我在将十六进制字符串转换为十进制表示时也遇到了问题?

好吧,你总是可以编写一个函数来自己解析十六进制格式的字符串:

int parse_hex(const char* p)
{
    int x = 0;
    for (; *p; ++p)
    {
        x = x * 16 + digit_value(*p);
    }
    return x;
}

digit_value的最便携版本是:

int digit_value(char c)
{
    switch (c)
    {
        case '0': return 0;
        case '1': return 1;
        case '2': return 2;
        case '3': return 3;
        case '4': return 4;
        case '5': return 5;
        case '6': return 6;
        case '7': return 7;
        case '8': return 8;
        case '9': return 9;
        case 'A': 
        case 'a': return 10;
        case 'B': 
        case 'b': return 11;
        case 'C': 
        case 'c': return 12;
        case 'D': 
        case 'd': return 13;
        case 'E': 
        case 'e': return 14;
        case 'F': 
        case 'f': return 15;
    }
}