How to generate a fixed length random number in Go?

huangapple go评论94阅读模式
英文:

How to generate a fixed length random number in Go?

问题

在Go语言中,生成固定长度的随机数的最快最简单的方法是什么?

假设要生成8位数的随机数,使用rand.Intn(100000000)的问题是结果可能远小于8位数,并且用前导零填充不是一个好的解决方案。

也就是说,我更关心随机性的质量,更关注其长度。所以我在思考,对于这个特定的问题,以下方法是否是最快最简单的方法?

99999999 - rand.Int63n(90000000)

也就是说,我猜想对于我的情况,Int63n可能比Intn更好。这是真的吗,还是只是一厢情愿?关于完整的8位数的随机性,这两种方法是否相同,或者其中一种比另一种更好?

最后,是否有比上述方法更好的方法?

更新:

请不要提供low + rand(hi-low)作为答案,因为每个人都知道这个方法。这相当于我现在正在做的,它并没有回答我真正的问题,即“关于完整的8位数的随机性,这两种方法是否相同,或者其中一种比另一种更好?”

如果没有人能回答这个问题,我将绘制两者之间的二维散点图,并自己找出答案...

谢谢

英文:

What is the fastest and simplest way to generate fixed length random numbers in Go?

Say to generate 8-digits long numbers, the problem with rand.Intn(100000000) is that the result might be far less than 8-digits, and padding it with leading zeros doesn't look like a good answer to me.

I.e., I care about the the quality of the randomness more in the sense of its length. So I'm thinking, for this specific problem, would the following be the fastest and simplest way to do it?

99999999 - rand.Int63n(90000000)

I.e., I guess Int63n might be better for my case than Intn. Is it ture, or it is only a wishful thinking? Regarding randomness of the full 8-digits, would the two be the same, or there is really one better than the other?

Finally, any better way than above?

UPDATE:

Please do not provide low + rand(hi-low) as the answer, as everyone knows that. It is equivalent of what I'm doing now, and it doesn't answer my real question, "Regarding randomness of the full 8-digits, would the two be the same, or there is really one better than the other? "

If nobody can answer that, I'll plot a 2-D scatter plot between the two and find out myself...

Thanks

答案1

得分: 15

这是一个用于在范围内生成数字的通用函数:

func rangeIn(low, hi int) int {
    return low + rand.Intn(hi-low)
}

在你的具体情况下,尝试生成8位数的数字,范围应为(10000000, 99999999)

你可以在kbd上查看它。

英文:

This is a general purpose function for generating numbers within a range

func rangeIn(low, hi int) int {
	return low + rand.Intn(hi-low)
}

See it on the <kbd>Playground</kbd>

In your specific case, trying to generate 8 digit numbers, the range would be (10000000, 99999999)

答案2

得分: 3

这取决于你想要使用的值范围。

  1. 如果你允许值范围为[0-99999999],并且希望在字符数小于8时填充零,那么可以使用类似于fmt.Sprintf("%08d", rand.Intn(100000000))的格式。

  2. 如果你不想填充零,而是希望在范围[10000000, 99999999]内生成随机数,那么可以使用类似于ranNumber := 10000000 + rand.Intn(90000000)的方法。

英文:

It depend on value range you want to use.

  1. If you allow value range [0-99999999] and padding zero ip number of char < 8, then use fmt like fmt.Sprintf(&quot;%08d&quot;,rand.Intn(100000000)).

  2. If you dont want padding, which value in range [10000000, 99999999], then give it a base like ranNumber := 10000000 + rand.Intn(90000000)`

答案3

得分: 2

在Playground上查看

crypto/rand包用于生成数字。

func generateRandomNumber(numberOfDigits int) (int, error) {
    maxLimit := int64(int(math.Pow10(numberOfDigits)) - 1)
    lowLimit := int(math.Pow10(numberOfDigits - 1))

    randomNumber, err := rand.Int(rand.Reader, big.NewInt(maxLimit))
    if err != nil {
        return 0, err
    }
    randomNumberInt := int(randomNumber.Int64())

    // 处理介于0、10^(n-1)之间的整数,例如n=4,处理介于(0, 999)之间的情况
    if randomNumberInt <= lowLimit {
        randomNumberInt += lowLimit
    }

    // 几乎不可能发生,只是为了安全起见
    if randomNumberInt > int(maxLimit) {
        randomNumberInt = int(maxLimit)
    }
    return randomNumberInt, nil
}
英文:

See it on Playground

crypto/rand package is used to generate number.

func generateRandomNumber(numberOfDigits int) (int, error) {
	maxLimit := int64(int(math.Pow10(numberOfDigits)) - 1)
	lowLimit := int(math.Pow10(numberOfDigits - 1))

	randomNumber, err := rand.Int(rand.Reader, big.NewInt(maxLimit))
	if err != nil {
		return 0, err
	}
	randomNumberInt := int(randomNumber.Int64())

	// Handling integers between 0, 10^(n-1) .. for n=4, handling cases between (0, 999)
	if randomNumberInt &lt;= lowLimit {
		randomNumberInt += lowLimit
	}

	// Never likely to occur, kust for safe side.
	if randomNumberInt &gt; int(maxLimit) {
		randomNumberInt = int(maxLimit)
	}
	return randomNumberInt, nil
}

答案4

得分: 1

我最近需要做类似的事情,但是需要指定字节长度(而不是数字位数),并且需要处理比最大int64还大的数字(所以要使用math/big.Int)。这是我的一般解决方案:

func generateRandomBigInt(numBytes int) (*big.Int, error) {
    value := make([]byte, numBytes)
    _, err := rand.Reader.Read(value)
    if err != nil {
        return nil, err
    }

    for true {
        if value[0] != 0 {
            break
        }
        firstByte := value[:1]
        _, err := rand.Reader.Read(firstByte)
        if err != nil {
            return nil, err
        }
    }

    return (&big.Int{}).SetBytes(value), nil
}

在 Playground 上查看(包含了代码注释)

英文:

I recently needed to do something like this, but with a certain byte length (rather than number of digits) and with numbers larger than max int64 (so using math/big.Int). Here was my general solution:

See on the Playground (with added code comments)

func generateRandomBigInt(numBytes int) (*big.Int, error) {
	value := make([]byte, numBytes)
	_, err := rand.Reader.Read(value)
	if err != nil {
		return nil, err
	}

	for true {
		if value[0] != 0 {
			break
		}
		firstByte := value[:1]
		_, err := rand.Reader.Read(firstByte)
		if err != nil {
			return nil, err
		}
	}

	return (&amp;big.Int{}).SetBytes(value), nil
}

huangapple
  • 本文由 发表于 2016年3月15日 10:27:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/36001621.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定