【问题标题】:Convert octal representation of a number to decimal将数字的八进制表示转换为十进制
【发布时间】:2011-10-31 13:51:56
【问题描述】:

假设一个向量或数组包含 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;

【问题讨论】:

  • “非负整数的八进制表示”到底是什么意思?你有一个独特的类型吗?
  • 对于搜索"base conversion" 时出现的任意数量的问题,这可能被视为重复。
  • @FredOverflow 我认为该向量包含一个数字,每个单元格包含一个数字(以 8 为基数)。我在纠结的是面试官是否会期望你从袖子里拿出一个任意精度的整数库。
  • @Oli : 我想知道我的代码出了什么问题,如果我们能做得更好..
  • @user:要找出你的代码有什么问题,我建议在调试器中单步调试。

标签: c++ hex


【解决方案1】:

任意精度的八进制到十进制的转换相当烦人,因为无法本地化计算。换句话说,八进制数的最高有效位的变化甚至会改变十进制表示中的最低有效位。

也就是说,我想我会将八进制数转换为一个以 1000000000 为基数的数字,然后将其打印出来(这是一个微不足道的问题,每个以 1000000000 为基数的数字只是微不足道地映射到 9 个以 10 为基数的数字) .

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

编辑

我尝试在 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;
}

在我的 PC 上,将 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 位八进制数。

【讨论】:

    【解决方案2】:

    这是我想出的:

    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';
    }
    

    我试过了,但它似乎不适用于 > 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;
        }
    }
    

    【讨论】:

    • 您的八进制代码是否适用于非常大的输入数组(10,000,000 个元素)?
    • @user:当然不是:“一个 int 通常有 32 位,而一个八进制数字有 3 位。因此,您的范围内不能有超过 10 个元素,否则 x 会溢出。”
    • 我明白了。我可以离线联系您并将确切的问题描述发送给您吗?我想要么我没有清楚地理解这个问题,要么我无法表达它。这将是一个很大的帮助。或者,也许您可​​以通过 aquarian.thunder@gmail.com 给我写信。谢谢!
    • @user:我只能告诉你,你显然不能只将值解析为 int。我对这个问题没有更多的见解。如果我偶然发现解决方案,我会更新我的答案。
    猜你喜欢
    • 2013-11-07
    • 2011-08-21
    • 1970-01-01
    • 2021-04-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-02-19
    • 1970-01-01
    相关资源
    最近更新 更多