javascript 在客户端和服务器上生成相同的伪随机数

qgelzfjb  于 2022-12-10  发布在  Java
关注(0)|答案(2)|浏览(268)

我有一个Web应用程序,在客户端使用JavaScript,在服务器端使用C#。我需要能够生成一组伪随机数--给定一个共享的种子--在客户端和服务器端都是相同的。有没有一个标准的方法可以做到这一点?显然,使用内置的PRNG库对于各自的语言是没有好处的,因为它们的算法是不同的。
我不想使用服务器端点为客户端提供随机数,因为我的客户端应用程序需要快速响应,这会增加延迟。它会 * 工作 *,但不是理想的。

8tntrjer

8tntrjer1#

下面是xorshift128+的C版本的javascript实现。根据维基百科文章,xorshift128+伪随机数生成器(PRNG)通过了BigCrush(经验随机性测试)。
注意xorshift128+被主流浏览器在实现Math.random时使用,所以它是一个可靠的算法,虽然不是cyber solid...

class XorShift128 {

  #state;
  
  static bitMask64 = ( 1n << 64n ) - 1n;
  static bitMask32 = ( 1n << 32n ) - 1n
  
  constructor( uint128Seed ) {
    this.#state = new BigUint64Array( [ ( uint128Seed >> 64n ) & XorShift128.bitMask64, uint128Seed & XorShift128.bitMask64 ] );
  }
  
  get nextValue() {
    let r = new BigUint64Array( this.#state );
    // C version t = r[0], s = r[1]
    this.#state[ 0 ] = r[ 1 ];
    r[ 0 ] ^= r[ 0 ] << 23n;
    r[ 0 ] ^= r[ 0 ] >> 18n;
    r[ 0 ] ^= r[ 1 ] ^ ( r[ 1 ] >> 5n );
    this.#state[ 1 ] = r[ 0 ];
    return Number( ( r[ 0 ] + r[ 1 ] ) & XorShift128.bitMask32 );
  }

}

console.log( `Set the seed to 0x8a5cd789635d2dff121fd2155c472f96n and generate 5 values...` );
let PRNG0 = new XorShift128( 0x8a5cd789635d2dff121fd2155c472f96n );
for ( let i = 0; i < 5; i++ ) {
  console.log( PRNG0.nextValue );
}

console.log( `Let's do it again...` );

let PRNG1 = new XorShift128( 0x8a5cd789635d2dff121fd2155c472f96n );
for ( let i = 0; i < 5; i++ ) {
  console.log( PRNG1.nextValue );
}

另请注意,方法nextValue中的局部变量使用BigUint6Array,因为这会自动将任何中间结果减少到64位。

epfja78i

epfja78i2#

在C#中的服务器上添加一个API端点,以返回单个随机数或随机数数组,然后从客户端调用它。
对服务器的调用不一定是低效的,这取决于您的逻辑和调用频率,从服务器调用它甚至可能是有意义的,特别是如果值的一致性非常重要的话,这可能是一个X-Y Problem,调用频率是多少,您可以容忍的最高延迟是多少,以及您从实现中记录的响应时间是什么类型。
是的,有一个标准的解决方案来解决类似的问题(在客户端和服务器中复制逻辑),那就是使用相同的随机数生成器算法和相同的 seed 值。例如,这就是我们如何在纸牌游戏中重放特定的手牌。
一个允许你在客户端和服务器端使用相同代码的纯C#解决方案是考虑Blazor而不是javascript。其他的解决方案是实现你自己的算法或者找到另一个已经移植到C#和javascript的算法。

相关问题