UINT8 year = 0x15;
,我想从year
在UINT8 decYear
得到十进制值15。我该怎么做 ?三江源
背景:我准备好了日,月,年。今天我分别获得了返回0x15,0x10,0x13的值。我想将它们转换为十进制值
UINT8 year = 0x15;
,我想从year
在UINT8 decYear
得到十进制值15。我该怎么做 ?三江源
背景:我准备好了日,月,年。今天我分别获得了返回0x15,0x10,0x13的值。我想将它们转换为十进制值
您正在使用的表达方式被称为Binary Coded Decimal和它的编码值的老办法。
为了得到你需要知道价值观是如何工作的二进制文件,以及如何使用位运算符在C.
比方说你有BCD编码值0x15
一个“正确”的十进制值,这是二进制00010101
。正如你可以看到1
存储在高nibble和低的5
。把它们带出自己是一个简单的按位与操作:
int year = 0x15;
int high_nibble = year & 0xf0; // Gets the high nibble, i.e. `0x10`
int low_nibble = year & 0x0f; // Gets the low nibble, i.e. `0x05`
现在你有两个变量,一个包含0x10
和其他0x05
。十六进制值0x05
与十进制值5
相同,因此不需要做任何事情。另一个值需要一些工作使其成为小数10
。为此,我们只需四位(00010000
将成为00000001
)移下来做
high_nibble >> 4
和“转换”为十进制您10
(1 * 10 == 10
)乘以值,最后加5
。
为了把它一起到一个单一的表达:
int decYear = ((year & 0xf0) >> 4) * 10 + (year & 0x0f);
很好解释。也许可以解释,decYear并不包含十进制值,但用二进制表示该十进制值是一种改进。你已经用“适当的”和“转换”来暗示它。或者,这可能超出了问题的范围。反正+1 –
首先:0x15
21
是(5×16^0)+(1×16^1),而不是15。
其次,尝试:
UINT8 year = 0x15;
printf("%d",year);
这是因为,最终没有将值保存为十六进制或十进制,而是保存为二进制。您使用的十六进制只是将您的系统转换为二进制文件的表示形式,如21
即可。
使其成为输出15很可能是非常困难的,让你甚至已经进入它的十六进制superflous的事实。它就像进入21
并要求我们图谋的方式对系统知道你的意思是15
如果你在十六进制的值从什么回报,尝试将其转换为一个字符串,然后切断的0x
部分它。
例如,如果你得到0x15
的价值,只是看它作为字符串,并用字符串操作切0X关闭。
0x15 CAN可以是十进制值15.它也可以是十进制值21.它也可以是NAK字符。还有很多其他的东西。这取决于它代表什么。 OP使用一个编码,其中0x15是十进制值15.他只是没有提到该编码是什么,也许他甚至不知道,因为他只是在学习。它可能是BCD。 –
在这种特殊情况下,你可以使用这个
UINT8 year = 0x15;
UINT8 yearD = year%16+ (year/16)*10;
有使用BCD编码
UINT8 yearD = ((year>>4)&0x0f)*10+ (year&0x0f);
说明更好的解决方案:
的0x15
二进制表示为00010101
。我们有高nibble与1(0001
)和低半字节5(0101
)。所以最终的结果是higher nibble value *10 + value of lower nibble
。为了得到较高的半字节值,我们做4 shift右边然后bitwise AND用0x0f
,4右移取高半字节值来降低半字节和bitwise and
用0x0f
清零上半字节,这是高半字节的实际值。为了获得更低的半字节值,我们需要清除更高的半字节值,以便我们使用year&0x0f
。
如果为0x15(十六进制)确实代表15(十进制),那么你很可能与输入买卖BCD format。
在这种情况下,从BCD转换为十进制(1)是通过提取输入的每个字符并正确添加它们来完成的。
我们的输入是一个8位的字节。
4个较少有意义的位(较低的半字节)表示单位,一个从0到9的数字。从A到F(十六进制)的值从不使用。
4个最有意义的位(高位半字节)表示数十。也是从0到9的数字。
如果提取它们,您将得到十进制(1)值,其公式为:十* 10个单位。 year & 0x0F
而上半段有右移和相同的二进制掩码:
我们可以用一个二进制掩码获得低四位(year>>4) & 0x0F
整个代码:
UINT8 year = 0x15;
assert (((year>>4) & 0x0F) < 10); // Ensure top nibble correctness
assert ((year & 0x0F) < 10); // Ensure low nibble correcness
int yearBin = ((year>>4) & 0x0F) * 10 + (year&0x0F);
printf("%d\n", (int)yearBin); // Print yearBin in decimal : 15 will be printed
printf("%x\n", (int)yearBin); // Print yearBin in hexadecimal :
// 0x15 will not be printed. 0xF will be printed.
(1)其实,我们不是从BCD转换为十进制。我们正在从BCD转换为二进制(最有可能是2补码)。这是printf中转换参数的选择,它使得它以十进制打印。
“不包含字母的十六进制值”是Binary Coded Decimal(BCD)。您可以转换BCD到十进制这样
#include <stdio.h>
#include <stdint.h>
uint8_t bcd2dec(uint8_t bcdval)
{
return (bcdval >> 4) * 10 + (bcdval & 0xF);
}
int main(int argc, char *argv[])
{
printf("Day %u\n", bcd2dec(0x13));
printf("Month %u\n", bcd2dec(0x10));
printf("Year %u\n", bcd2dec(0x15));
return 0;
}
程序输出:
Day 13
Month 10
Year 15
所以,如果我理解正确的话,你想从0×15得到15。
您可以使用下面的方法:
char buffer[4];
UINT8 year = 0x15;
sprintf(buffer, "%x", year);
如果打印缓冲区,你会得到“15”作为一个字符串。你可以这样做:
UINT8 decYear = atoi(buffer);
你不知道。所有值最终都以*二进制*存储,十进制或十六进制只是表示值的方式。您为'year'指定的值是二进制'00010101',如果使用十进制符号打印它,则会得到'21'。 –
顺便说一句@JoachimPileborg 0x15在十进制中不是37,它是21 – Guillaume
是的,可以说以十六进制格式表示的值实际上代表了十进制值。像这里的0x15代表小数点15(即2105)。所以如何转换它 – user3061597