Maple:RNG不是随机的
Maple: RNG is not random
我是"finding Pi"用Monte Carlo方法,但是答案不正确。原始代码是:
RandomTools[MersenneTwister]: with(Statistics):
tries := 10000:
s := 0;
for i to tries do
if GenerateFloat()^2+GenerateFloat()^2 < 1 then s := s+1 end if;
end do:
evalf(4*s/tries)
它给出了 2.8-2.85 左右的答案
当我将代码更改为
s := 0;
x := Array([seq(GenerateFloat(), i = 1 .. tries)]);
y := Array([seq(GenerateFloat(), i = 1 .. tries)]);
for i to tries do
if x[i]^2+y[i]^2 < 1 then s := s+1 end if;
end do:
evalf(4*s/tries)
那么答案是正确的。我不知道为什么我不能在 "for" 循环中生成数字。
我发现它的均值相同,但方差不同。
对于:
tries := 100000;
A := Array([seq(GenerateFloat(), i = 1 .. 2*tries)]);
s1 := Array([seq(A[i]^2+A[tries+i]^2, i = 1 .. tries)]);
Mean(s1);
Variance(s1);
s2 := Array([seq(GenerateFloat()^2+GenerateFloat()^2, i = 1 .. tries)]);
Mean(s2);
Variance(s2);
输出为:
0.6702112097021581
0.17845439723457215
0.664707674135025
0.35463131700965245
有什么问题吗? GenerateFloat() 应尽可能统一。
自动简化正在改变您的,
GenerateFloat()^2+GenerateFloat()^2
进入,
2*GenerateFloat()^2
在评估 GenerateFloat()
之前。
要使其按预期工作,一个简单的更改就是将它们分开。例如,
restart:
with(RandomTools[MersenneTwister]):
tries := 10^4:
s := 0:
for i to tries do
t1,t2 := GenerateFloat(),GenerateFloat();
if t1^2+t2^2 < 1 then s := s+1 end if;
end do:
evalf(4*s/tries);
另一种方法是使用稍微不同的结构,它不会自动简化。考虑一下,单右引号(uneval 引号)不会停止自动简化(如果需要,这是术语的定义)。
'f()^2 + f()^2';
2
2 f()
但是下面不会自动简化,
a:=1:
'f()^2 + a*f()^2';
2 2
f() + a f()
因此,另一个简单的解决方法是,
restart:
with(RandomTools[MersenneTwister]):
tries := 10^4:
s := 0:
a := 1;
for i to tries do
if GenerateFloat()^2 + a*GenerateFloat()^2 < 1 then s := s+1 end if;
end do:
evalf(4*s/tries);
我是"finding Pi"用Monte Carlo方法,但是答案不正确。原始代码是:
RandomTools[MersenneTwister]: with(Statistics):
tries := 10000:
s := 0;
for i to tries do
if GenerateFloat()^2+GenerateFloat()^2 < 1 then s := s+1 end if;
end do:
evalf(4*s/tries)
它给出了 2.8-2.85 左右的答案
当我将代码更改为
s := 0;
x := Array([seq(GenerateFloat(), i = 1 .. tries)]);
y := Array([seq(GenerateFloat(), i = 1 .. tries)]);
for i to tries do
if x[i]^2+y[i]^2 < 1 then s := s+1 end if;
end do:
evalf(4*s/tries)
那么答案是正确的。我不知道为什么我不能在 "for" 循环中生成数字。
我发现它的均值相同,但方差不同。 对于:
tries := 100000;
A := Array([seq(GenerateFloat(), i = 1 .. 2*tries)]);
s1 := Array([seq(A[i]^2+A[tries+i]^2, i = 1 .. tries)]);
Mean(s1);
Variance(s1);
s2 := Array([seq(GenerateFloat()^2+GenerateFloat()^2, i = 1 .. tries)]);
Mean(s2);
Variance(s2);
输出为:
0.6702112097021581
0.17845439723457215
0.664707674135025
0.35463131700965245
有什么问题吗? GenerateFloat() 应尽可能统一。
自动简化正在改变您的,
GenerateFloat()^2+GenerateFloat()^2
进入,
2*GenerateFloat()^2
在评估 GenerateFloat()
之前。
要使其按预期工作,一个简单的更改就是将它们分开。例如,
restart:
with(RandomTools[MersenneTwister]):
tries := 10^4:
s := 0:
for i to tries do
t1,t2 := GenerateFloat(),GenerateFloat();
if t1^2+t2^2 < 1 then s := s+1 end if;
end do:
evalf(4*s/tries);
另一种方法是使用稍微不同的结构,它不会自动简化。考虑一下,单右引号(uneval 引号)不会停止自动简化(如果需要,这是术语的定义)。
'f()^2 + f()^2';
2
2 f()
但是下面不会自动简化,
a:=1:
'f()^2 + a*f()^2';
2 2
f() + a f()
因此,另一个简单的解决方法是,
restart:
with(RandomTools[MersenneTwister]):
tries := 10^4:
s := 0:
a := 1;
for i to tries do
if GenerateFloat()^2 + a*GenerateFloat()^2 < 1 then s := s+1 end if;
end do:
evalf(4*s/tries);