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

发布于 2024-07-26 19:54:29 字数 501 浏览 9 评论 0原文

我正在使用 C 语言的 PIC 微处理器。它是 16F,因此它不能容纳大于 32 位的整数(无符号 int32 是可用的最大数据大小)

从阅读器中,我收到一个 5 字节身份证号码。 为了传输它,我必须逐位编码为 BCD。 我无法将其冲刺为字符串,因为它大于数据大小,并且无法处理它。 我无法划分它,因为没有为它定义任何操作。

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

编辑:

我收到一系列 5 个字节的数字:

FF-FF-FF-FF-FF

我需要将其转换为十进制

0123456789012

(13位,十进制长度256^5)通过RS232发送。 第二个函数(获取 ASCII 并发送)我已经可以使用它了,但我需要完整数字的字符串表示形式,然后才能对其执行任何操作。

I am working with a PIC microprocessor, in C. It's a 16F, so it can't hold integers larger than 32bits (unsigned int32 is the largest datasize available)

From a reader, I receive a 5 byte ID code. To transmit it, I have to encoded to BCD, digit by digit. I can't sprint it to a string, as it is larger that the data size, and can't process it. I can't divide it because no operation is defined for it.

I can't figure out any solution possible, does anyone have dealt with this before?

EDIT:

I receive the number in a series of 5 bytes:

FF-FF-FF-FF-FF

I need to convert it to decimal

0123456789012

(13 digits, length of 256^5 in decimal) to send it through RS232. The second function (Take the ASCII, and send it) I already have it working, but I need the string representation of the full number before I can do anything with it.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

内心旳酸楚 2024-08-02 19:54:29

假设您有 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 x 2**16)。
第二项也可以在不溢出的情况下计算(因为 x < 2**16y <2**24)。

这基本上是 2 位值的基数 2**24 的长除法,但预先计算的项已知除数为 1000。选择 1000 是因为它是 10 的最小幂比2**8

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

((2**32) * x + y) % 1000 = ((2**32) * x) % 1000 + y % 1000 (modulo 1000)
                         = (296 * x) % 1000 + y % 1000     (modulo 1000)
((2**32) * x + y) % 1000 = ((296 * x) % 1000 + y % 1000) % 1000

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

顺便说一句,如果我是你,我会检查结果:我还没有对此进行测试,并且可能我在某个地方犯了错误。 应该很容易与 PC 上使用常规方法在 64 位整数中完成的 bcd 转换结果进行比较。

Assuming you have 32 bit arithmetic: 2**24 = 16777216, so taking x as the most significant 2 bytes and y as the least significant 3:

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

The first term can be calculated in 32 bits without overflow (since x < 2**16).
The second term can also be calculated without overflow (since x < 2**16 and y < 2**24).

This is basically long division in base 2**24 of a 2-digit value, but with terms pre-calculated knowing that the divisor is 1000. One thousand is chosen because it's the least power of 10 greater than 2**8.

So, first compute the lowest three digits, use the fact that (2**32) % 1000 == 296. So this time we'll take x as the highest byte and y as the low 4 bytes

((2**32) * x + y) % 1000 = ((2**32) * x) % 1000 + y % 1000 (modulo 1000)
                         = (296 * x) % 1000 + y % 1000     (modulo 1000)
((2**32) * x + y) % 1000 = ((296 * x) % 1000 + y % 1000) % 1000

Then divide the original number by 1000 using the formula above. Then you're safely into 32 bit territory and can churn out the remaining digits using the normal loop.

Btw, I'd check the results if I were you: I haven't tested this and it's possible I've made an error somewhere. It should be easy to compare against the results of bcd conversions done using the usual means in a 64-bit integer on a PC.

明月夜 2024-08-02 19:54:29

我要做的就是对编码为字符串(类似于 BigNum)的数字实现加法和乘法。 这样,您可以将 ID 的最高有效字节转换为字符串“A”,将其与字符串“4294967296”(256^4)相乘,得到字符串“B”,然后将 ID 的 4 个最低有效字节转换为 sprintf另一个字符串“C”,最后添加“B”和“C”。

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

What I would do, is implement addition and multiplication for numbers coded as a string (sort of BigNum). That way, you can sprintf the most significant byte of your ID to a string "A", multiply it with the string "4294967296" (256^4) giving you string "B", sprintf the 4 least significant bytes of your ID in another string "C", and finally adding "B" and "C".

It's not very sexy, especially on a micro-controller, but it works :)

悲喜皆因你 2024-08-02 19:54:29

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

无效 BCD32(int32u numIn)
{
int8u 数字 = 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);                           

}

The PIC16F does not have a hardware multiply or divide unit, so unless you are multiplying or dividing by a power of 2, it is taxing to the processor. Here is a routine that does a BCD on a 32 bit number and doesn't require division or multiplication. You could adapt this to a 5 byte number by doing it in chunks.

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);                           

}

对岸观火 2024-08-02 19:54:29

您始终可以自己手动将其“sprintf”为字符串。 逐个字节地检查数据,并通过附加单个字符将其转换为数字字符串。

You can always "sprintf" it to a string manually yourself. go over the data byte after byte and convert it to a numerical string by appending individual characters.

方圜几里 2024-08-02 19:54:29

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

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

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

The core of this problem I would say is one of "long division" to convert to decimal. Not entirely unlike long division you learned in grade school, though with binary numbers, long division is much simpler. But its still a lot of work.

try:
http://mathforum.org/library/drmath/view/55951.html

You will have to implement your own multi-byte subtraction and shift routines.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文