2015-10-13 145 views
1

我有C:转换十六进制值相同的十进制数

UINT8 year = 0x15; 

,我想从yearUINT8 decYear得到十进制值15。我该怎么做 ?三江源

背景:我准备好了日,月,年。今天我分别获得了返回0x15,0x10,0x13的值。我想将它们转换为十进制值

+0

你不知道。所有值最终都以*二进制*存储,十进制或十六进制只是表示值的方式。您为'year'指定的值是二进制'00010101',如果使用十进制符号打印它,则会得到'21'。 –

+2

顺便说一句@JoachimPileborg 0x15在十进制中不是37,它是21 – Guillaume

+0

是的,可以说以十六进制格式表示的值实际上代表了十进制值。像这里的0x15代表小数点15(即2105)。所以如何转换它 – user3061597

回答

3

您正在使用的表达方式被称为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 

和“转换”为十进制您101 * 10 == 10)乘以值,最后加5

为了把它一起到一个单一的表达:

int decYear = ((year & 0xf0) >> 4) * 10 + (year & 0x0f); 
+1

很好解释。也许可以解释,decYear并不包含十进制值,但用二进制表示该十进制值是一种改进。你已经用“适当的”和“转换”来暗示它。或者,这可能超出了问题的范围。反正+1 –

0

首先:0x1521是(5×16^0)+(1×16^1),而不是15。

其次,尝试:

UINT8 year = 0x15; 
printf("%d",year); 

这是因为,最终没有将值保存为十六进制或十进制,而是保存为二进制。您使用的十六进制只是将您的系统转换为二进制文件的表示形式,如21即可。

使其成为输出15很可能是非常困难的,让你甚至已经进入它的十六进制superflous的事实。它就像进入21并要求我们图谋的方式对系统知道你的意思是15

如果你在十六进制的值从什么回报,尝试将其转换为一个字符串,然后切断的0x部分它。

例如,如果你得到0x15的价值,只是看它作为字符串,并用字符串操作切0X关闭。

+0

0x15 CAN可以是十进制值15.它也可以是十进制值21.它也可以是NAK字符。还有很多其他的东西。这取决于它代表什么。 OP使用一个编码,其中0x15是十进制值15.他只是没有提到该编码是什么,也许他甚至不知道,因为他只是在学习。它可能是BCD。 –

1

在这种特殊情况下,你可以使用这个

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 AND0x0f,4右移取高半字节值来降低半字节和bitwise and0x0f清零上半字节,这是高半字节的实际值。为了获得更低的半字节值,我们需要清除更高的半字节值,以便我们使用year&0x0f

0

如果为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中转换参数的选择,它使得它以十进制打印。

0

“不包含字母的十六进制值”是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

所以,如果我理解正确的话,你想从0×15得到15。

您可以使用下面的方法:

char buffer[4]; 
UINT8 year = 0x15; 

sprintf(buffer, "%x", year); 

如果打印缓冲区,你会得到“15”作为一个字符串。你可以这样做:

UINT8 decYear = atoi(buffer); 
相关问题