解码十六进制数字的最快方法

问题描述 投票:0回答:4

到目前为止,我想出的最好的公式是:

char c = 'd';  // or any other hex character
int value = (((c & 0x1F) + 9) % 25;

注意它不含分支,但确实包含昂贵的模型操作。

我可以做得更好吗?
    

您可以在没有模块化和没有分支的情况下做到这一点,只有几个班次和减法。

int value = (c & 0x0F) + 9 - ((c&0x10)>>1) - ((c&0x10)>>4);

我只是从您的公式开始,并使用了一个事实,即

c&0x10
algorithm hex
4个回答
5
投票
0

则是

0x10
注意,正如评论中指出的那样,编译器将优化编译器将倍增和添加的mod提出,但这仍然应该更好,因为编译器没有前提条件:

0-9

是十六进制数字。
    
如果您有一个快速乘以:
c
    

int value = (c & 0x0f) + 9 * (c >> 6)

非常直接的小提琴。

demo


5
投票
略有不同的变体

(d & 0xf) + ((d & 0x40) >> 3) + ((d & 0x40) >> 6)
saves另一个位

4
投票
操作。 ther的变体基本上将6位乘以9(与Mark Ransom的答案相同,但没有硬件乘法)。

我晚了派对,但丹尼尔·莱米尔(Daniel Lemire)基准了

几个版本

,得出的结论是,使用简单的查找表的速度是“花哨的数学功能”的两倍。从他的文章中进行复制:

and where

uint32_t hex_to_u32_lookup(const uint8_t *src) { uint32_t v1 = digittoval[src[0]]; uint32_t v2 = digittoval[src[1]]; uint32_t v3 = digittoval[src[2]]; uint32_t v4 = digittoval[src[3]]; return v1 << 12 | v2 << 8 | v3 << 4 | v4; }

“是一个256个字节阵列,其中48(或'0')映射到0、65(或'a')被映射到10,依此类推”。

我甚至后来参加聚会,但我来找一个答案。  这里接受的答案使用了6种操作,对我来说似乎并不最佳,所以我进行了一些修补并提出了这些操作。
absumsuming您将其限制为ACII字符集,如果您在X64上,并且编译器很不错,那么这将优化一些比较,一个比较,两个添加和一个CMOV;因此,4个操作和一个CMOV

digittoval

假设您已经将其验证为十六进制字符。

如果您需要这样做...

u8 r = (u8)c & 0x1f; r = (r <= 6) ? r += 9 : r -= 16;

0
投票
r==如果是十六进制的数字。

这将优化到测试,一个CMOV,2位和一个变化。标志还作为即时值加载,因此处理器不必进入内存。 我尚未使用“查找表”方法测试这些方法,但是直觉表明,只要您可以保证它不会引起cache Miss。 *注意:“ U8”和“ U64”是我自己的无签名类型

	

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.