当没有数据类型可以保存完整数字时,将十六进制转换为十进制

时间:2009-07-17 13:34:24

标签: c algorithm bignum pic

好的,所以我在C中使用PIC微处理器。它是16F,因此它不能保存大于32位的整数(unsigned int32是可用的最大数据量)

从阅读器中,我收到一个5字节的ID代码。为了传输它,我必须逐位编码为BCD。我无法将其打印到字符串,因为它比数据大小大,并且无法处理它。我无法分割它,因为没有为它定义任何操作。

我无法找出任何可能的解决方案,之前有没有人处理过这个问题?

编辑:

我收到一系列5个字节的数字:“FF-FF-FF-FF-FF”。我需要将它转换为十进制“0123456789012”(13位数,长度为256 ^ 5十进制),通过RS232发送。第二个功能(取ASCII,然后发送)我已经有了它的工作,但我需要完整数字的字符串表示才能用它做任何事情。

5 个答案:

答案 0 :(得分:4)

假设您有32位算术:2 ** 24 = 16777216,所以将x视为最重要的2字节,将y视为最不重要的3:

  (16777216 * x + y) / 1000 
= (16777000 * x + 216 * x + y) / 1000
= 16777 * x + (216 * x + y) / 1000

第一个术语可以32位计算而不会溢出(因为x < 2**16)。 第二个术语也可以在没有溢出的情况下计算(从x < 2**16y < 2**24)。

这基本上是2位数值的基础2**24中的长除法,但是预先知道除数是1000的项。选择了1000,因为它的最小幂大于10 {{ 1}}。

因此,首先计算最低的三位数,使用2**8的事实。所以这次我们将x作为最高字节,y作为低4字节

(2**32) % 1000 == 296

然后使用上面的公式将原始数字除以1000。然后你可以安全地进入32位区域,并可以使用正常循环生成剩余的数字。

是的,如果我是你,我会检查结果:我没有测试过这个,我可能在某个地方犯了错误。应该很容易与使用PC上64位整数的常用方法完成的bcd转换结果进行比较。

答案 1 :(得分:1)

我要做的是对编码为字符串的数字(一种BigNum)实现加法和乘法。这样,您可以将ID的最重要字节sprintf为字符串“A”,将其与字符串“4294967296”(256 ^ 4)相乘,为您提供字符串“B”,sprintf为您ID中的4个最低字节另一个字符串“C”,最后添加“B”和“C”。

它不是很性感,特别是在微控制器上,但它有效:)

答案 2 :(得分:1)

PIC16F没有硬件乘法或除法单位,因此,除非您乘以或除以2的幂,否则它对处理器造成负担。这是一个在32位数字上执行BCD且不需要除法或乘法的例程。您可以通过以块为单位将其调整为5字节数。

void BCD32(int32u numIn) {     int8u digit = 0;

while (numIn >= 1000000000)
{
    numIn -= 1000000000;
    digit++;
}    
debug[0] = digit + 48;   
digit = 0;
while (numIn >= 100000000)
{
    numIn -= 100000000;
    digit++;
}    
debug[1] = digit + 48;            
digit = 0;
while (numIn >= 10000000)
{
    numIn -= 10000000;
    digit++;
}    
debug[2] = digit + 48;            
digit = 0;
while (numIn >= 1000000)
{
    numIn -= 1000000;
    digit++;
}    
debug[3] = digit + 48;            
digit = 0;
while (numIn >= 100000)
{
    numIn -= 100000;
    digit++;
}    
debug[4] = digit + 48;            
digit = 0;
while (numIn >= 10000)
{
    numIn -= 10000;
    digit++;
}
debug[5] = digit + 48;        
digit = 0;
while (numIn >= 1000)
{
    numIn -= 1000;
    digit++;
}
debug[6] = digit + 48;    
digit = 0;    
while (numIn >= 100)
{
    numIn -= 100;
    digit++;
}
debug[7] = digit + 48;

digit = 0;
while (numIn >= 10)
{
    numIn -= 10;
    digit++;
}
debug[8] = digit + 48;

digit = 0;
while (numIn >= 1)
{
    numIn -= 1;
    digit++;
}
debug[9] = digit + 48;    
debug[10] = CARRIAGE_RETURN;
debug[11] = NEW_LINE_FEED;
SendUart(12);                           

}

答案 3 :(得分:0)

您可以随时手动将其“sprintf”为字符串。遍历字节后的数据字节,并通过附加单个字符将其转换为数字字符串。

答案 4 :(得分:0)

我想说的这个问题的核心是转换为十进制的“长除法”之一。与你在小学阶段学到的长分并不完全不同,尽管使用二进制数,长分割更简单。但它仍然需要做很多工作。

尝试:
http://mathforum.org/library/drmath/view/55951.html

您必须实现自己的多字节减法和移位例程。