我想通过模运算将md5哈希字符串映射到工作日数字(0-6)。因此,我需要将字符哈希值转换为整数(数字)。我还没有找到一种方法来输出字节形式的哈希值而不是ascii字符串(通过digest
包)。任何基础R或不同方法的提示都会受到赞赏。
答案 0 :(得分:1)
如果你真的想这样做,你将需要多精度算术,因为单个md5散列有128位,这太大而不适合普通的整数值。这可以使用gmp包来完成。
library('digest');
library('gmp');
as.integer(do.call(c,lapply(strsplit(sapply(letters,digest,'md5'),''), function(x) sum(as.bigz(match(x,c(0:9,letters[1:6]))-1)*as.bigz(16)^((length(x)-1):0)) ))%%7);
## [1] 3 2 1 1 5 5 5 5 1 4 4 6 5 3 5 4 0 2 0 4 5 4 6 3 6 1
让我们打破这一点:
sapply(letters,digest,'md5')
## a b c ...
## "127a2ec00989b9f7faf671ed470be7f8" "ddf100612805359cd81fdc5ce3b9fbba" "6e7a8c1c098e8817e3df3fd1b21149d1" ...
我想将此算法设计为矢量化,并决定使用内置letters
向量作为26个任意输入值以进行演示。不幸的是,完全矢量化算法的梦想(即没有隐藏的循环)立刻被破灭,因为digest()
由于某种原因没有被矢量化,这就是为什么我必须在这里使用sapply()
来生成一个矢量对应于输入的md5哈希值。
strsplit(...,'')
## $a
## [1] "1" "2" "7" "a" "2" "e" "c" "0" "0" "9" "8" "9" "b" "9" "f" "7" "f" "a" "f" "6" "7" "1" "e" "d" "4" "7" "0" "b" "e" "7" "f" "8"
##
## $b
## [1] "d" "d" "f" "1" "0" "0" "6" "1" "2" "8" "0" "5" "3" "5" "9" "c" "d" "8" "1" "f" "d" "c" "5" "c" "e" "3" "b" "9" "f" "b" "b" "a"
##
## $c
## [1] "6" "e" "7" "a" "8" "c" "1" "c" "0" "9" "8" "e" "8" "8" "1" "7" "e" "3" "d" "f" "3" "f" "d" "1" "b" "2" "1" "1" "4" "9" "d" "1"
## ...
将散列拆分为字符向量,每个元素是散列的一个十六进制数字。我们现在有一个包含26个字符向量的列表。
lapply(..., function(x) ... )
一次处理一个字符向量。潜入函数(将给出与输入字符串x
对应的'a'
的值的示例输出):
match(x,c(0:9,letters[1:6]))-1
## [1] 1 2 7 10 2 14 12 0 0 9 8 9 11 9 15 7 15 10 15 6 7 1 14 13 4 7 0 11 14 7 15 8
通过查找十六进制数字序列(c(0:9,letters[1:6])
)中的索引并减去一个,将每个数字的值作为普通旧整数返回。
as.bigz(...)
## Big Integer ('bigz') object of length 32:
## [1] 1 2 7 10 2 14 12 0 0 9 8 9 11 9 15 7 15 10 15 6 7 1 14 13 4 7 0 11 14 7 15 8
转换为大整数,这是我们即将进行的算术所必需的。
...*as.bigz(16)^((length(x)-1):0)
## Big Integer ('bigz') object of length 32:
## [1] 21267647932558653966460912964485513216 2658455991569831745807614120560689152 581537248155900694395415588872650752 51922968585348276285304963292200960 649037107316853453566312041152512
## [6] 283953734451123385935261518004224 15211807202738752817960438464512 0 0 2785365088392105618523029504
## [11] 154742504910672534362390528 10880332376531662572355584 831136500985057557610496 42501298345826806923264 4427218577690292387840
## [16] 129127208515966861312 17293822569102704640 720575940379279360 67553994410557440 1688849860263936
## [21] 123145302310912 1099511627776 962072674304 55834574848 1073741824
## [26] 117440512 0 720896 57344 1792
## [31] 240 8
将散列处理为大端十六进制数,将每个数字值乘以其位值。
sum(...)
## Big Integer ('bigz') :
## [1] 24560512346470571536449760694956189688
将每个地方值加权的数字值相加以获得散列的bigz表示。
这样就完成了lapply()
功能。因此,从lapply()
调用中出来的是与哈希值对应的bigz值列表:
lapply(..., function(x) ... )
## $a
## Big Integer ('bigz') :
## [1] 24560512346470571536449760694956189688
##
## $b
## Big Integer ('bigz') :
## [1] 295010738308890763454498908323798711226
##
## $c
## Big Integer ('bigz') :
## [1] 146851381511772731860674382282097773009
## ...
do.call(c,...)
## Big Integer ('bigz') object of length 26:
## [1] 24560512346470571536449760694956189688 295010738308890763454498908323798711226 146851381511772731860674382282097773009 277896596675540352347406615789605003835 196274166648971101707441276945175337351
## [6] 152164057440943545205375583549802787690 177176961461451259509149953911555923867 104722841650969351697149582356678916643 338417919426764038104581950237023359466 337938589168387959049175020406476846763
## [11] 182882473465429367490220828342074920857 80661780033646501757972845962914093977 251563583963884775614900275564391350478 279860001817578054753205218523665183571 158142488666995307556311659134646734337
## [16] 116423801372716526262639744414150237351 97172586736798383425273805088952414146 316382305028166656556246910315962582893 245775506345085992020540282526076959865 96713787940004003047734284080139522561
## [21] 227309401343419671779216095382349119699 250431221767618781785406207793096585421 33680856367414392588062933086110875192 119974848773126933055729663395967301868 296965764652868210844163281547943654188
## [26] 118199003122415992890118393158735259681
这个“列出”列表。注意:我尝试了sapply()
而不是lapply()
,或者unlist()
,但都没有效果。这可能与bigz类有关,可能是因为bigz值的向量实际上被奇怪地编码为单个原始向量。
...%%7
## Big Integer ('bigz') object of length 26:
## [1] 3 2 1 1 5 5 5 5 1 4 4 6 5 3 5 4 0 2 0 4 5 4 6 3 6 1
最后我们可以在7上取模数。
as.integer(...)
## [1] 3 2 1 1 5 5 5 5 1 4 4 6 5 3 5 4 0 2 0 4 5 4 6 3 6 1
最后一步是从bigz转换回普通旧整数。