寻找 rand() 函数的种子 TI-84 编程
Finding the Seed of the rand() Function TI-84 Programming
我对 TI-84 rand() 函数进行了大量研究。它使用 L'Ecuyer 算法生成伪随机数。不过我有一个有趣的案例。
如果为 rand() 函数提供了正确的种子,它将始终生成相同的数字。那么,给定 rand() 函数生成的第一个随机数,是否可以找到函数的种子?
让变量 X 代表未知种子。
X->rand
rand->D
Disp D
输出:
0.114820491
根据这些信息,是否可以计算出 rand() 函数的种子?你能以某种方式从 TI-84 的 rand() 算法向后工作吗?
我找到了一种解决方案,但我认为它不是最有效的系统。以下是我用来彻底搜索随机数匹配项的程序。
0→C
Repeat X=0.114820491
Disp C
C→rand
rand→X
C+1→C
End
Disp "Done!"
此程序测试 rand 函数的每个种子,直到它最终找到产生所需随机数的种子。
这个系统的问题在于存在大量的可能性。在这种情况下,该程序只需要 运行 40,000 次多一点,但在某些情况下,该程序需要 运行 数百万次才能找到匹配的种子。但是,如果种子相对较小,则此方法有效。
这不是最好的解决方案,但它是一个解决方案。
查看@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;
}
在OPs第一个随机数的情况下,它给出以下输出:
$ 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
在回答这个问题时,我是站在巨人的肩膀上,使用@richard 在 Whosebug 问题的回答中提供的代码。如果有更好的方式来提供归因,请告诉我或简单地编辑这个答案。
我对 TI-84 rand() 函数进行了大量研究。它使用 L'Ecuyer 算法生成伪随机数。不过我有一个有趣的案例。
如果为 rand() 函数提供了正确的种子,它将始终生成相同的数字。那么,给定 rand() 函数生成的第一个随机数,是否可以找到函数的种子?
让变量 X 代表未知种子。
X->rand
rand->D
Disp D
输出:
0.114820491
根据这些信息,是否可以计算出 rand() 函数的种子?你能以某种方式从 TI-84 的 rand() 算法向后工作吗?
我找到了一种解决方案,但我认为它不是最有效的系统。以下是我用来彻底搜索随机数匹配项的程序。
0→C
Repeat X=0.114820491
Disp C
C→rand
rand→X
C+1→C
End
Disp "Done!"
此程序测试 rand 函数的每个种子,直到它最终找到产生所需随机数的种子。
这个系统的问题在于存在大量的可能性。在这种情况下,该程序只需要 运行 40,000 次多一点,但在某些情况下,该程序需要 运行 数百万次才能找到匹配的种子。但是,如果种子相对较小,则此方法有效。
这不是最好的解决方案,但它是一个解决方案。
查看@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;
}
在OPs第一个随机数的情况下,它给出以下输出:
$ 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
在回答这个问题时,我是站在巨人的肩膀上,使用@richard 在