Algorithm 查找rand()函数TI-84编程的种子

Algorithm 查找rand()函数TI-84编程的种子,algorithm,random,ti-basic,Algorithm,Random,Ti Basic,我对TI-84 rand()函数做了很多研究。它使用L'Ecuyer算法生成伪随机数。然而,我有一个有趣的案例 如果为rand()函数指定了正确的种子,它将始终生成相同的数字。那么,给定rand()函数生成的第一个随机数,是否可以找到函数的种子 让变量X表示未知种子 X->rand rand->D Disp D 输出: 0.114820491 根据这些信息,是否可以计算rand()函数的种子?你能从Ti-84的RAND()算法中向后地工作吗?< /

我对TI-84 rand()函数做了很多研究。它使用L'Ecuyer算法生成伪随机数。然而,我有一个有趣的案例

如果为rand()函数指定了正确的种子,它将始终生成相同的数字。那么,给定rand()函数生成的第一个随机数,是否可以找到函数的种子

让变量X表示未知种子

    X->rand
    rand->D
    Disp D
输出:

    0.114820491

根据这些信息,是否可以计算rand()函数的种子?你能从Ti-84的RAND()算法中向后地工作吗?< /P> < P>我找到了一个解决方案,但我不认为它是最有效的系统。下面是我用来彻底搜索与兰特号码匹配的程序

0→C

Repeat X=0.114820491
Disp C
C→rand
rand→X
C+1→C
End

Disp "Done!"
该程序测试rand函数的每个种子,直到最终找到生成所需随机数的种子

这个系统的问题是存在大量的可能性。在这种情况下,该程序只需运行40000次多一点,但在某些情况下,在找到匹配的种子之前,该程序将运行数百万次。但是,如果种子相对较小,则此方法有效

这不是最好的解决方案,但它是一个解决方案


有关更精确的方法,请参见@JimD.的答案。

不,根据经验,仅根据第一个生成的随机数计算种子是不可能的,因为它不是唯一的。以下代码将对给定第一个随机数的种子执行暴力搜索:

#include <stdio.h>
#include <stdint.h>
#include <math.h>
#include <stdlib.h>

int64_t mod1  = 2147483563;
int64_t mod2  = 2147483399;
int64_t mult1 = 40014;
int64_t mult2 = 40692;
int64_t seed1,seed2;

void Seed(int64_t n){
  if(n<0) //Perform an abs
    n = -n;
  if(n==0){
    seed1 = 12345; //Gotta love these seed values!
    seed2 = 67890;
  } else {
    seed1 = (mult1*n)%mod1;
    seed2 = n%mod2;
  }
}

double Generate(){
  double result;
  seed1  = (seed1*mult1)%mod1;
  seed2  = (seed2*mult2)%mod2;
  result = (double)(seed1-seed2)/(double)mod1;
  if(result<0)
    result = result+1;
  return result;
}

int main(int argc, char **argv){
  double x = 0.114820491; // Mattkx4's value
  double r;
  int64_t n;
  int i;

  if (argc > 2) {
    printf("USAGE: %s <1st generated random number>\n", argv[0]);
    return 1;
  } else if (argc == 2) {
    x = atof(argv[1]);
    printf("[Looking for seed generating %.10f]\n", x);
  } else {
    printf("[Looking for seed generating default value of %.10f]\n", x);
  }

  for (n=0; n<= 2147483647; n++) {
    Seed(n);
    r = Generate();
    if (fabs(r-x) < 10e-10) {
      printf("HIT: seed is %ld; G()=%.10f, G()-x=%.12f\n", (long) n, r, r-x);
      for (i=0; i<5; i++) {
        printf("  G() = %.10f\n", Generate());
      }
    }
  }

  return 0;
}

在回答这个问题时,我站在巨人的肩膀上,使用@richard在回答这个问题时提供的代码。如果有更好的方法提供属性,请告诉我或编辑此答案。

声称“出厂默认种子为0”。这并不能回答您的问题,但它确实有一些有趣的信息,特别是关于值“1”。我理解这一点@吉米。我键入的程序只是一个参考示例。在我的情况下,我试图破解一个加密程序。我得到了生成的第一个随机数,但我不知道种子是什么。有没有办法根据rand()生成的第一个随机数来确定它的种子是什么?我的问题有意义吗?或者我应该重新措辞吗?我不确定我对随机数生成器的属性了解得不够。如果你做反向运行这个算法的思想实验,我认为你可以得到很多可能的s1和s2值,这些值可以生成特定的输出。但是如果它是第一个输出,那么s1和s2是从种子n派生出来的。我不知道这会将可能性的数量减少到1。因此,您可能需要超过1个。还请注意,显示的值可能不足以让您知道确切的32位浮点,这也增加了可能性的数量。是我指的算法。我认为只有2^32-1个有效的不同种子值,所以我彻底搜索了你的值,找到了4个种子:41817、196206349、392370881和588535413。它们都会产生不同的序列。因此,看起来您无法从第一个值获得唯一的种子,但这并不意味着您无法解密消息。
$ time ./a.out
[Looking for seed generating default value of 0.1148204910]
HIT: seed is 41817; G()=0.1148204909, G()-x=-0.000000000055
  G() = 0.1928098124
  G() = 0.8785866698
  G() = 0.7541802051
  G() = 0.3236799652
  G() = 0.2698472063
HIT: seed is 196206349; G()=0.1148204909, G()-x=-0.000000000055
  G() = 0.7255189385
  G() = 0.3079613984
  G() = 0.8041985209
  G() = 0.0959226401
  G() = 0.7729820570
HIT: seed is 392370881; G()=0.1148204909, G()-x=-0.000000000055
  G() = 0.2582281409
  G() = 0.7373361269
  G() = 0.8542168367
  G() = 0.8681653150
  G() = 0.2761169842
HIT: seed is 588535413; G()=0.1148204909, G()-x=-0.000000000055
  G() = 0.7909372669
  G() = 0.1667108555
  G() = 0.9042350761
  G() = 0.6404079899
  G() = 0.7792519113
HIT: seed is 1869313916; G()=0.1148204919, G()-x=0.000000000876
  G() = 0.9421831845
  G() = 0.2660259263
  G() = 0.9001868100
  G() = 0.3563914254
  G() = 0.3884731955
HIT: seed is 2065478448; G()=0.1148204919, G()-x=0.000000000876
  G() = 0.4748923105
  G() = 0.6954006549
  G() = 0.9502050494
  G() = 0.1286341003
  G() = 0.8916080463

real    1m24.132s
user    1m24.179s
sys 0m0.000s