C# 随机数(Long)

6

我正在尝试基于C#中的种子生成一个数字。唯一的问题是,种子太大了,无法作为int32。有没有办法可以使用long作为种子?

是的,种子必须是long。


@J0HN 我正在计算史莱姆在我的世界中的生成位置。 - user1599078
1
@user1599078 - 即使您使用了获得的Long,您如何保证生成的伪随机数与Java实现的匹配? - keyboardP
1
这对我来说就像希腊语一样难懂。你为什么认为使用长整型作为种子会有帮助呢?+100500 给 @keyboardP 的评论(抱歉,SO 只允许点赞一次 :)) - J0HN
1
@user1599078 - 是的,只要“Random”函数的内部实现匹配,你就可以得到相同的输出。在这种情况下,你甚至不需要“Random”类,因此可以创建自己的方法来接受“Long”。 - keyboardP
1
你可以查看java.lang.Random的源代码,然后将其转换为C#;这可能不是太难。算法在这里:http://docs.oracle.com/javase/6/docs/api/java/util/Random.html#next%28int%29 - Matthew Watson
显示剩余11条评论
3个回答

2
这是我从Java规范中移植过来的 Java.Util.Random 的 C# 版本。
最好的方法是编写一个Java程序生成一堆数字,并检查此C#版本是否生成相同的数字。
public sealed class JavaRng
{
    public JavaRng(long seed)
    {
        _seed = (seed ^ LARGE_PRIME) & ((1L << 48) - 1);
    }

    public int NextInt(int n)
    {
        if (n <= 0)
            throw new ArgumentOutOfRangeException("n", n, "n must be positive");

        if ((n & -n) == n)  // i.e., n is a power of 2
            return (int)((n * (long)next(31)) >> 31);

        int bits, val;

        do
        {
            bits = next(31);
            val = bits % n;
        } while (bits - val + (n-1) < 0);
        return val;
    }

    private int next(int bits)
    {
        _seed = (_seed*LARGE_PRIME + SMALL_PRIME) & ((1L << 48) - 1);
        return (int) (((uint)_seed) >> (48 - bits));
    }

    private long _seed;

    private const long LARGE_PRIME = 0x5DEECE66DL;
    private const long SMALL_PRIME = 0xBL;
}

2
对于今天看到这个问题的任何人,.NET 6及以上版本提供了 Random.NextInt64,它具有以下重载:
  • NextInt64()

    • 返回一个非负随机整数。
  • NextInt64(Int64)

    • 返回一个小于指定最大值的非负随机整数。
  • NextInt64(Int64, Int64)

    • 返回一个在指定范围内的随机整数。

2
这些方法生成随机的64位数字。问题是如何使用一个与之无关的64位种子初始化Random实例。 - Lucas

0
我会选择@Dyppl在这里提供的答案:长范围内的随机数,是这样吗? 将此函数放置在需要生成随机数的代码可以访问的位置:
long LongRandom(long min, long max, Random rand) 
{
    byte[] buf = new byte[8];
    rand.NextBytes(buf);
    long longRand = BitConverter.ToInt64(buf, 0);
    return (Math.Abs(longRand % (max - min)) + min);
}

然后这样调用函数:
long r = LongRandom(100000000000000000, 100000000000000050, new Random());

10
根据链接中的评论(以及我自己的测试),这种方法不起作用:“不正常工作。LongRandom(long.MinValue,long.MaxValue,new Random()),总是返回-9223372036854775808。无论如何,Math.Abs()会破坏一位,让你只剩下63个随机位。如果你只有63个随机位,就不能提供64位的随机数。” - Jake Drew
这些方法生成一个随机的64位数字。问题是如何使用一个不相关的64位种子初始化Random实例。 - Lucas

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接