【问题标题】:Interpreting a hex number as decimal将十六进制数解释为十进制
【发布时间】:2014-04-15 11:09:10
【问题描述】:

我有一个运行 C 代码的嵌入式系统,它运行起来非常简单;它通过串行连接读取字符,将接收到的字符解释为十六进制数字,并根据接收到的内容继续执行其他操作。但是,有一种非常特殊的情况,接收到的字符是十进制而不是十六进制。由于这种情况非常罕见(一种错误情况的错误情况),我不希望修改实际的字符接收来决定是否将接收到的值解释为 dec 或 hex,而是添加一个快速算法到我将数字更改为十进制的情况处理。

您认为最快(如在最高效的处理器方面)执行此操作的方式是什么?由于该软件在小型 MCU 上运行,因此任何 C 库函数都不是一个选项,因为我不希望添加更多不必要的#include,因此我正在寻找纯数学算法。

为了清楚起见,我并不是在问最快的方法来进行基本的十六进制到十进制转换,如 0x45 -> dec 69,但我想做的是转换例如。 0x120 转化为十进制 120。

提前致谢!

编辑:对不起,我会尝试更详细地解释。实际代码太长了,我认为没有必要在这里粘贴。所以这就是发生的事情:

首先我从串行线上读取一个接收到的数字,比如说“25”。然后我把它变成十六进制数,所以我有一个带有读取值的变量,比如说 X = 0x25。这已经很好了,我不想对此进行修改。在这种非常特殊的情况下,我现在想做的只是改变变量的解释,而不是 X == 0x25,X==25。十六进制的 0x25 变成十进制的 25。这种变化必须有某种数学公式,而不需要任何特定于处理器的指令或库函数?

【问题讨论】:

  • 它被称为BCD。如果这是一种罕见的情况,我会在可用的情况下使用库函数。有些处理器有 BCD 相关指令。
  • 如果您要查找的字符序列是 0x120,那么只需创建一个像这样的字符指针:char *decimal = &inChar[2];int number = atoi(decimal);... 虽然我怀疑您在寻找什么for 有点复杂。你真的应该详细说明这一点(显示一些代码,更具体)
  • 对不起,我会尝试更详细地解释。实际代码太长了,我认为没有必要。所以这就是发生的事情:
  • 请编辑您的问题以改进它。
  • 你怎么知道这是你收到的十进制值,因为你在评论中说你没有在十六进制值前面得到 0x,例如25 既是有效的十六进制数,也是有效的十进制数。

标签: c hex radix


【解决方案1】:

如果我理解正确,您已经将 ASCII 字符流转换为 char/int 变量,假设它们是十六进制数字流。在某些情况下,它们实际上是十进制数字流(例如,您收到 45 并将其视为十六进制,得到一个值为 69 的变量,而在一种特殊情况下,您实际上希望它的值是45.

假设两个字符,(一般是00-ff,但对于“本来是十进制的”,我们说的是00-99)然后:

int hexVal = GetHexStringFromSerialPort() ;
int decVal = 10*(hexVal >> 4) + (hexVal & 0x0f) ;

应该可以解决问题。如果你有更长的字符串,你需要进一步扩展这个概念。

【讨论】:

  • 这看起来正是我要找的,我会看看我在哪里结束的。谢谢!
【解决方案2】:

只要像这样做一个简单的while 循环,假设onumdnum 是无符号整数

dnum = 0;
while (onum) {
  digit = onum & 0xF;
  dnum = dnum*10 + digit;
  onum >>= 4;
}

这假设onum 确实是您描述的形式(没有>9 的十六进制数字)。它只是从您的数字中提取最不重要的十六进制数字并将其添加到您的小数中。

【讨论】:

  • 这会“反转”数字。对于 onum = 0x1234,您将在 dnum 中得到 4321。
  • @MichaelWalz,对。必须再次进行第二次循环才能恢复。
【解决方案3】:

检查您的字符串是否以 0x 字符开头并删除它们应该可以解决问题。

【讨论】:

  • 我收到的字符数据没有以 0x 为前缀,我收到的只是逗号分隔形式的数字。此外,我不希望在实际接收程序中添加任何类型的检查,我宁愿在情况需要时操纵接收到的号码。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-16
  • 1970-01-01
  • 2015-01-26
  • 1970-01-01
相关资源
最近更新 更多