如何停止/冻结/暂停不稳定的 RAND / RANDBETWEEN / RANDARRAY?

How to stop / freeze / pause volatile RAND / RANDBETWEEN / RANDARRAY?

有没有一种简单的方法(解决方法)如何禁用易变函数的自动重新计算,例如 =RAND() =RANDARRAY() =RANDBETWEEN() google传播sheet(?)

在构建密钥生成器的情况下,我们需要处理多个 RANDBETWEEN 输出,每次单元格更改都会重新计算,而那些 RANDBETWEEN 数字不能在我们不断编辑的 sheet 中停留更长时间。

那里有一个错误的冷冻插件和许多非通用的脚本变体,需要安装和一定程度的改装/知识,那么如何用旧方法做到这一点?

首先,让我们看看狐狸是怎么说的

=WHATTHEFOXSAY()

是一个独特的彩蛋google sheets函数(由@kishkin发现)随机生成一个pre-set用户需求的文本字符串,这是一个大问题,因为虽然生成是随机的,但重新计算不受 onEditonChangeonOpen 事件,因此通过一些调整,我们可以生成一个随机数,而无需使用无法冻结的 RAND()RANDBETWEEN()ARRAYRAND() 等可变函数/暂停

狐狸只会说这些话:

A-oo-oo-oo-ooo!
Hatee-hatee-hatee-ho!   
Wa-pa-pa-pa-pa-pa-pow!  
A-bubu-duh-bubu-dwee-dum    
Fraka-kaka-kaka-kaka-kow!   
Jacha-chacha-chacha-chow!   
Gering-ding-ding-ding-dingeringeding    
Joff-tchoff-tchoff-tchoffo-tchoffo-tchoff!  
    

例如。我们用这个函数得到的是 8 次机会中的随机 1 次,这并不多,所以我们需要扩大它(比方说按 9 条狐狸尾巴的顺序)。遗憾的是 ARRAYFORMULA 不支持函数,因此我们需要构建 {} 数组:

={WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY();
  WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY();
  WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY()}

然后我们将这种狐狸语转换成如下数字:

=INDEX(LEN(
 {WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY();
  WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY();
  WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY()}))

接下来,我们需要一个开关。没什么特别的,只是一个简单的 IF 语句和一个复选框:

=ARRAYFORMULA(LEN(IF(A1=TRUE, 
 {WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY();
  WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY();
  WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY()}, 
 {WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY();
  WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY();
  WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY()})))

这将使我们能够通过切换复选框来完全控制重新计算。最后一步是通过将所有数字与 PRODUCT 相乘来增加我们最初的 1/8 机会,从而增加我们的随机性,为了更有趣,我们将它乘以 3 次方的 PI

=ARRAYFORMULA(PI()^3*PRODUCT(LEN(IF(A1=TRUE, 
 {WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY();
  WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY();
  WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY()}, 
 {WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY();
  WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY();
  WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY()}))))



无限制blade 有效

到目前为止,我们似乎没有创建有用的东西...一个复选框,其中有一些随机查找的数字来回循环(在这一点上根本不是随机的)...所以让我们继续下一个级别。我们真正的 objective 是创建一串数字,我们从中提取某些部分并将它们转换为最终输出。为此,我们需要利用 SEQUENCE 的力量,我们 TRANSPOSE 获得额外的力量:

=TRANSPOSE(SEQUENCE(5, 4, 3, 2))

这转换为 5 列乘以 4 行的网格,其中第一个单元格以数字 3 开头,每个下一个单元格 (column-wise) 的值都大 2

现在让我们定义最终输出:

  • 3 个独特的字符串
  • 每个字符串有 16 个字符
  • 数字从 09
  • 和小写字母从af

此时我们的 SEQUENCE 将如下所示:

=TRANSPOSE(SEQUENCE(16, 3, 29, 73))

16 = columns
3  = rows
29 = starting point
73 = stepping

对于第三个和第四个参数 (29 & 73) 我们可以使用一些不错的 prime numbers 并再次乘以我们的整个序列by PI()^3 以增加混乱。我们还需要将我们的数字输出转换为纯文本字符串以避免 1.79769E+308 符号,因此我们使用 TEXT 来表示:

=ARRAYFORMULA(TEXT(PI()^3*PRODUCT(LEN(IF(A1=TRUE, 
 {WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY();
  WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY();
  WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY()}, 
 {WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY();
  WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY();
  WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY()})))*
 TRANSPOSE(SEQUENCE(16, 3, 29, 73))*PI()^3, "0"))

此时,我们在整个网格中的数字分布非常好



终极十六进制/密码生成器

那里的每个角色都有自己的代码。你可以通过 运行 这个 AF 在你的 sheet:

中查看
=ARRAYFORMULA({{"character", "code"};
 {CHAR(SEQUENCE(2500, 1, 33)), SEQUENCE(2500, 1, 33)}})

ROW(48:57)     = 0-9
ROW(65:90)     = A-Z
ROW(97:122)    = a-z
ROW(1040:1071) = А-Я
ROW(1072:1103) = а-я
ROW(913-937)   = Α-Ω
ROW(945-969)   = α-ω

出于示例目的,我们需要 0-9a-f:

的字符代码
ROW(48:57)     = 0-9
ROW(97:102)    = a-f

我们将它放在数组 {} 中并按降序排序(这是因为我们不想将自己锁定在到达列表中较低位置的字符之外)。然后我们 JOIN 它与或 | 分隔符准备好 regex-ed:

=JOIN("|", SORT({ROW(48:57); ROW(97:102)}, 1, ))

基本上,我们的想法是 REGEXEXTRACT 从我们的数字网格中的 above-joined 字符串中找到第一个数字,以防万一没有匹配我们添加 IFNA 回退来自我们范围的一些数字(本例中的 102):

=ARRAYFORMULA(IFNA(REGEXEXTRACT(
 TEXT(PI()^3*PRODUCT(LEN(IF(A1=TRUE, 
 {WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY();
  WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY();
  WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY()}, 
 {WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY();
  WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY();
  WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY()})))*
 TRANSPOSE(SEQUENCE(16, 3, 29, 73))*PI()^3, "0"), 
 JOIN("|", SORT({ROW(48:57); ROW(97:102)}, 1, ))), 102))

并召唤CHAR个角色:

=ARRAYFORMULA(CHAR(IFNA(REGEXEXTRACT(
 TEXT(PI()^3*PRODUCT(LEN(IF(A1=TRUE, 
 {WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY();
  WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY();
  WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY()}, 
 {WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY();
  WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY();
  WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY()})))*
 TRANSPOSE(SEQUENCE(16, 3, 29, 73))*PI()^3, "0"), 
 JOIN("|", SORT({ROW(48:57); ROW(97:102)}, 1, ))), 102)))

现在最后一步是用查询粉碎它并删除剩余的空格 - 更多关于查询粉碎 here

=ARRAYFORMULA(SUBSTITUTE(FLATTEN(QUERY(TRANSPOSE(
 CHAR(IFNA(REGEXEXTRACT(TEXT(PI()^3*PRODUCT(LEN(IF(A1=TRUE, 
 {WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY();
  WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY();
  WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY()}, 
 {WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY();
  WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY();
  WHATTHEFOXSAY(); WHATTHEFOXSAY(); WHATTHEFOXSAY()})))*
 TRANSPOSE(SEQUENCE(16, 3, 29, 73))*PI()^3, "0"), 
 JOIN("|", SORT({ROW(48:57); ROW(97:102)}, 1, ))), 102))),,
 9^9)), " ", ))


总结

  • 那些字符串真的是随机的吗?当然不是——它们只是“足够随机”,因为我们知道“熵”规则,但祝你好运,手工破解它...
  • 主要的关键点是没有发生第 3 方重新计算,因此值保持暂停状态并在切换复选框时生成新值
  • 这些字符串会在一段时间内重复出现吗? - 是的,他们可以,就像常规 RAND() 函数
  • 有没有可能一次生成两个相同的密钥? - 是的,它可能会发生,但可以通过多种方式来降低几率或引入 UNIQUE() 或添加更多狐狸尾巴
  • 请注意这个特殊情况:onOpen 事件将在每个复选框切换后 re-calculate WHATTHEFOXSAY() 一次!!因此,如果您需要工作,建议在每次切换复选框后使用 F5 键刷新 spreadsheet第i个冻结值

如果您希望在某些时间段内有一个新的自动生成的字符串,您可以插入一个可变函数 TODAY()NOW() - 但请注意,每次您编辑任何内容时都会重新计算当您不编辑任何内容时的单元格或每分钟/小时
(取决于 ..//File > Spreadsheet 设置)

如何不在每个单元格更改时 re-calculate 和在每个复选框切换或每 6 分钟时 re-calculate?一个星期一次?每个奇数月?只有周一和周三?每 11 个小时? 可能! 我们需要一个更简单的 IF 语句放置在 spreadsheet 的任何地方,它将托管我们的逻辑门并输出数组 {} 中的值星座,因此我们可以将我们的狐狸公式引用到不包含具有易失性元素的公式的单元格。 example: