将字符串转换为整数以进行模运算

时间:2015-03-30 13:47:29

标签: r type-conversion

我想通过模运算将md5哈希字符串映射到工作日数字(0-6)。因此,我需要将字符哈希值转换为整数(数字)。我还没有找到一种方法来输出字节形式的哈希值而不是ascii字符串(通过digest包)。任何基础R或不同方法的提示都会受到赞赏。

1 个答案:

答案 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转换回普通旧整数。