【问题标题】:How to generate random hex string in javascript如何在javascript中生成随机十六进制字符串
【发布时间】:2019-10-10 14:54:40
【问题描述】:

如何生成只包含给定长度的十六进制字符(0123456789abcdef)的随机字符串?

【问题讨论】:

  • 究竟什么是“十六进制字符”,即aAbBfF 是否有效?另外,“正常”随机还是加密强随机?
  • 更新问题。正常随机就够了……

标签: javascript lodash


【解决方案1】:

使用扩展运算符和.map()的简短替代方法


演示1

const genRanHex = size => [...Array(size)].map(() => Math.floor(Math.random() * 16).toString(16)).join('');

console.log(genRanHex(6));
console.log(genRanHex(12));
console.log(genRanHex(3));

  1. 传入一个数字 (size) 作为返回字符串的长度。

  2. 定义一个空数组 (result) 和一个范围在 [0-9][a-f] (hexRef) 的字符串数组。

  3. for 循环的每次迭代中,生成一个 0 到 15 的随机数,并将其用作来自步骤 2 的字符串数组 (hexRef) 的值的索引 -- 然后是 push() 的值到第 2 步中的空数组 (result)。

  4. 将数组 (result) 作为 join('')ed 字符串返回。


演示2

const getRanHex = size => {
  let result = [];
  let hexRef = ['0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'];

  for (let n = 0; n < size; n++) {
    result.push(hexRef[Math.floor(Math.random() * 16)]);
  }
  return result.join('');
}

console.log(getRanHex(6));
console.log(getRanHex(12));
console.log(getRanHex(3));

【讨论】:

  • parseInt 从字符串返回整数,其中包括使用指定基数编码的数字,而不是相反
  • 你完全正确,我不知道我在想什么,感谢您发现这一点,@LukášŘádek 查看更新。
  • 你知道吗?,你也让我上当了。乍一看,这似乎是合理的。投票从 -1 到 +1 ?
  • 2个客户端生成时不能唯一的可能性有多大
  • @Naga 不够安全。我最终创建了一个 miro-service 来跟踪跨客户端的 16 个 char 十六进制字符串
【解决方案2】:

NodeJS 用户

您可以使用crypto 模块中的randomBytes 来生成给定大小的加密强伪随机数据。您可以轻松地将其转换为十六进制。

import crypto from "crypto";

const randomString = crypto.randomBytes(8).toString("hex");

console.log(randomString)  // ee48d32e6c724c4d

上面的代码sn-p生成一个随机的8字节十六进制数,你可以随意操作长度。

【讨论】:

    【解决方案3】:

    有几种方法。一种方法是从预定义的字符串中提取:

    function genHexString(len) {
        const hex = '0123456789ABCDEF';
        let output = '';
        for (let i = 0; i < len; ++i) {
            output += hex.charAt(Math.floor(Math.random() * hex.length));
        }
        return output;
    }
    

    另一种方法是附加一个0到15之间的随机数,用toString转换为十六进制:

    function genHexString(len) {
        let output = '';
        for (let i = 0; i < len; ++i) {
            output += (Math.floor(Math.random() * 16)).toString(16);
        }
        return output;
    }
    

    【讨论】:

      【解决方案4】:

      如果你可以使用 lodash 库,这里是代码 sn-p 来生成一个 16 字符的字符串:

      let randomString = _.times(16, () => (Math.random()*0xF<<0).toString(16)).join('');
      

      【讨论】:

      • 如果您只想要 4 位数字,我认为您可以将前 16 位更改为 4 位。
      【解决方案5】:

      这是一个避免一次构建一个数字的版本;它可能只适合短篇。

      function genHexString(len) {
          const str = Math.floor(Math.random() * Math.pow(16, len)).toString(16);
          return "0".repeat(len - str.length) + str;
      }
      

      【讨论】:

        【解决方案6】:

        这适用于最长 13 的长度:

        randomHex = length => (
                '0'.repeat(length) 
                + Math.floor((Math.random() * 16 ** length))
                .toString(16)
            ).slice(-length);
        
        console.log(randomHex(4));
        console.log(randomHex(6));
        console.log(randomHex(13));
        console.log(randomHex(20));

        【讨论】:

          【解决方案7】:

          这会安全地生成一个 32 字节的随机字符串并将其编码为十六进制(64 个字符)。

          Array.from(crypto.getRandomValues(new Uint8Array(32)))
              .map(b => b.toString(16).padStart(2, '0')).join('');
          

          长版:

          function generateRandomHexString(numBytes) {
              const bytes = crypto.getRandomValues(new Uint8Array(numBytes));
              const array = Array.from(bytes);
              const hexPairs = array.map(b => b.toString(16).padStart(2, '0'));
              return hexPairs.join('')
          }
          

          【讨论】:

            【解决方案8】:

            一个 Math.random() 调用 (A) 最多可以快速获取 7 个字符:

            const halfBytesIn35 = 7 // = 3.5 bytes
            const byte35 = Math.pow(16, halfBytesIn35)
            const bytes35 = () => ((Math.random() * byte35) | 0).toString(16).padStart(halfBytesIn35,'0')
            console.log('A: ' + bytes35())
            
            const bytes65 = len => Math.floor(Math.random() * Math.pow(16, len*2)).toString(16).padStart(len,'0')
            console.log('B: ' + bytes65(6))
            
            function moreBytes (len) {
              len *= 2; // alternative: len <<= 1 if you do not use half bytes. This might allow optimizations based on len always being an Integer then.
              let builder = "";
              while (len > 0) {
                builder += bytes35()
                len -= 7
              }
              return builder.slice(0,len)
            }
            console.log('C: ' + moreBytes(16))

            如果您打算高频使用,请存储 Math.pow 常量。

            第 8 个字母溢出到二进制楼层的符号位中。

            您可以使用 Math.floor 代替 (B) 一次调用最多 13 个字符,甚至可以循环生成任意长度 (C)。

            请注意,这可用于定义过早优化。如果您的瓶颈确实是随机数的创建,请考虑使用 LUT。如果您正在为嵌入式开发,这很常见。 (在这种情况下,不知何故被 javascript 卡住了,但没有时间生成随机数)

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2012-05-10
              • 2012-11-06
              • 2012-05-07
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2014-03-07
              • 2013-09-14
              相关资源
              最近更新 更多