Bigquery 中的模运算。计算 `x % y`,其中 `x` 是一个 128 位数字

Modulo arithmetic in Bigquery. Compute `x % y`, where `x` is a 128-bit number

将字符串的 MD5 作为整数 x 的 128 位表示,我如何在 Google Bigquery 中计算 x % y,其中 y 将通常相对较小(大约 1000)?

Bigquery 有一个 MD5 函数,返回一个 BYTES 类型的结果,有 16 个字节(即 128 位)。

(背景:这是为了计算确定性伪随机数。但是,由于遗留和兼容性原因,我在算法上没有灵活性!即使我们知道它有一个 (very slight) bias .)

每天需要针对不同的输入字符串和不同的模数执行 millions/billions 次,因此希望它可以高效地完成。作为回退,我可以用另一种语言在外部计算它,然后再上传到 Bigquery;但如果我可以直接在 Bigquery 中执行此操作,那就太好了。

我研究了很多数论,所以也许我们可以使用一些数学技巧。但是,我仍然停留在更基本的 BiqQuery 问题上

使用 power of math 和较长的 SQL 函数:

CREATE TEMP FUNCTION modulo_md5(str ANY TYPE, m ANY TYPE) AS ((
  SELECT MOD(MOD(MOD(MOD(MOD(MOD(MOD(MOD(MOD(MOD(MOD(MOD(MOD(MOD(MOD(MOD(0 
    * 256 + num[OFFSET(0)], m ) 
    * 256 + num[OFFSET(1)], m )  
    * 256 + num[OFFSET(2)], m ) 
    * 256 + num[OFFSET(3)], m ) 
    * 256 + num[OFFSET(4)], m )  
    * 256 + num[OFFSET(5)], m ) 
    * 256 + num[OFFSET(6)], m ) 
    * 256 + num[OFFSET(7)], m )  
    * 256 + num[OFFSET(8)], m ) 
    * 256 + num[OFFSET(9)], m ) 
    * 256 + num[OFFSET(10)], m )  
    * 256 + num[OFFSET(11)], m ) 
    * 256 + num[OFFSET(12)], m ) 
    * 256 + num[OFFSET(13)], m )  
    * 256 + num[OFFSET(14)], m ) 
    * 256 + num[OFFSET(15)], m ) 
  FROM (SELECT TO_CODE_POINTS(MD5(str)) num)
));


SELECT title, modulo_md5(title, 177) result, TO_HEX(MD5(title)) md5
FROM `fh-bigquery.wikipedia_v3.pageviews_2019` 
WHERE wiki='en'
LIMIT 100000

现在您可以将其用作持久共享 UDF:

SELECT fhoffa.x.modulo_md5("any string", 177) result