【问题标题】:How to convert Binary Coded Decimal to int in C++如何在 C++ 中将二进制编码的十进制转换为 int
【发布时间】:2018-02-04 06:25:06
【问题描述】:

在 c++ 中给定一个 0x80 的十六进制值(作为 uint16_t 提供),我将如何将这些数字提取到一个 int 变量中。我不想将十六进制转换为 int,而是想将数字提取为 int,例如,对于 0x80,我想要一个 80 的 int,而不是 128,或者对于 0x55,我想要 55 而不是 85,等等。

uint16_t hex = 0x80;
uint8_t val = ???; // Needs to be 80

只有十六进制数字的数字永远不会出现。 IE。输入将仅包含十进制数字。
例如。 0x08、0x09、0x10、0x11、0x12等

【问题讨论】:

  • 至少您需要显示保存十六进制值的变量。是std::string,是char数组还是......。如果你到目前为止已经完成了任何代码,请发布它。
  • 请尽可能多地显示minimal reproducible example。 IE。显示输入是如何到达的以及将结果放在哪里。
  • 0xaa 将被表示为什么?你也知道十六进制位数的上限吗?
  • 这永远不会发生,将提供变量,如 0x08、0x09、0x10、0x11、0x12 等
  • @MattBrailsford 你应该改进你的问题标题,这完全是误导。二进制编码的十进制,是您所追求的正确术语。

标签: c++ hex converter bcd


【解决方案1】:

一个简单的实现如下:

int from_hex(uint16_t h)
{
    int d = 0;
    int power = 1;
    while (h)
    {
        // assert(h % 16 < 10)
        d += h % 16 * power;
        h /= 16;
        power *= 10;
    }
    return d;
}

感谢Minor Threat 提供以下服务:

int from_hex(uint16_t h)
{
    int d = 0;
    int power = 1;
    while (h)
    {
        // assert(h % 16 < 10)
        d += (h & 15) * power;
        h >>= 4;
        power *= 10;
    }
    return d;
}

我很高兴知道我的代码是否有问题

【讨论】:

  • 有人能告诉我为什么当他们反对投票吗?我是新人所以不知道如何正确回答
  • 很抱歉你认为我以前的 cmets 是一种侮辱,我很惊讶你有这么高的声誉,但问一个相对简单的问题
  • "easy" 是相对的。如果你知道这很容易。我只是不明白为什么您需要在回复中包含判断陈述。什么都不做,只会让 OP 觉得寻求帮助很愚蠢,毕竟这就是 SO 的目的。
  • 我很抱歉我的错误,请原谅我的无知
【解决方案2】:

既然你说十六进制数从不包含“a”、“b”等。这段代码应该可以解决问题:

#include <iostream>

int main() {
    uint16_t in = 0x4321;

    int t = (1000 * ((in & 0xf000) / (16*16*16))) + 
             (100 * ((in & 0xf00) / (16*16))) + 
              (10 * ((in & 0xf0) / 16)) + 
               (1 * ((in & 0xf) / 1));
    std::cout << t << std::endl;
    return 0;
}

输出

4321

说明

= 0xWZYX 中的 16 位十六进制数计算为

in = W*16^3 + Z*16^2 + Y*16^1 + X*16^0 (or just W*16^3 + Z*16^2 + Y*16^1 + X)

什么时候做

in & 0xf000 you get 0xW000

什么时候做

0xW000 / 16^3 you get 0x000W or just W

什么时候做

1000 * W you get W000 decimal

然后为每个数字重复该模式。

使用 shift 的替代实现

#include <iostream>

int main() {
    uint16_t in = 0x9321;

    int t = (1000 * ((in & 0xf000) >> 12)) + 
             (100 * ((in & 0xf00) >> 8)) + 
              (10 * ((in & 0xf0) >> 4)) + 
               (1 * ((in & 0xf) >> 0));
    std::cout << t << std::endl;
    return 0;
}

对于 16 位无符号整数,可以写出四行。但是,如果您想为更大的 unsigned int 使用类似的函数,则最好执行循环以使代码更加紧凑和可维护。

使用循环的 64 位解决方案

#include <iostream>

int64_t directHexToDec(uint64_t in)
{
    int64_t res = 0;
    uint64_t mask = 0xf;
    uint64_t sh = 0;
    uint64_t mul = 1;
    for (int i=0; i<16; ++i)
    {
        res += mul * ((in & mask) >> sh);
        mul *= 10;
        mask <<= 4;
        sh += 4;
    }
    return res;
}

int main() {
    uint64_t in = 0x987654321;

    int64_t t = directHexToDec(in);
    std::cout << t << std::endl;
    return 0;
}

输出

987654321

【讨论】:

  • 感谢您花时间解释,而不是像其他人一样侮辱我缺乏知识。
  • 如果数字太大,你会全部硬编码吗?
  • @Raindrop7 - 我可能会做一个循环。我们有 4 行 uint16_t 很容易处理。对于 uint64_t 这将是 16 行并且变得有点混乱。下一步... 128 unsigned int .... 这肯定会调用循环。在答案中,我避免循环以保持简单。
  • 是的,尤其是 OP 无法自行处理。添加一个循环然后编辑。
  • @Raindrop7 - 你是在问我是否也要添加循环解决方案吗?
【解决方案3】:

使用流和字符串转换的更简单的答案。请注意,这不适用于 0x0A0X0B、... 值。

uint16_t val = 0x80;
std::stringstream stream;
stream << std::hex << val;
std::string resultStr(stream.str());
// In case of 0xYY hex value be carefull that YY fits into an uint8_t, 
// otherwise  this will overflow
uint8_t result = static_cast<uint8_t>(std::stoi(resultStr));

【讨论】:

    【解决方案4】:

    这应该适用于十六进制

    #include <iostream>
    
    unsigned int foo(unsigned int hex)
    {
        return  hex - (hex >> 4) * 6;
    }
    
    /* Test */
    int main()
    {
        unsigned int vals[] = {0x08, 0x09, 0x10, 0x11, 0x12, 0x80};
    
        for (int i = 0; i < sizeof(vals) / sizeof(vals[0]); i++)
            std::cout << foo(vals[i]) << std::endl;
    
        return 0;
    }
    

    结果:

    8
    9
    10
    11
    12
    80
    

    【讨论】:

    • 为 OP 添加一些解释。 +1
    猜你喜欢
    • 2020-04-03
    • 2014-02-13
    • 1970-01-01
    • 1970-01-01
    • 2012-12-26
    • 2021-05-16
    • 2015-12-02
    • 2019-08-29
    相关资源
    最近更新 更多