在ruby中使用迭代计算pi
对于学校的作业,我试图使用高斯-勒让德算法计算pi,以测试cpu效率。 因此,我用Ruby编写了一个程序。 该程序应迭代500000000次,并显示用于该程序的时间。但每次它都会在一秒钟内执行。 我的问题: 有没有更好的方法进行迭代,使其真正重复5亿次并显示pi和时间在ruby中使用迭代计算pi,ruby,loops,pi,Ruby,Loops,Pi,对于学校的作业,我试图使用高斯-勒让德算法计算pi,以测试cpu效率。 因此,我用Ruby编写了一个程序。 该程序应迭代500000000次,并显示用于该程序的时间。但每次它都会在一秒钟内执行。 我的问题: 有没有更好的方法进行迭代,使其真正重复5亿次并显示pi和时间 include Math a = 1 b = 1/sqrt(2) t = 0.25 p = 1 i = 0 imax = 500000000 start = Time.now until i = imax an = (a/
include Math
a = 1
b = 1/sqrt(2)
t = 0.25
p = 1
i = 0
imax = 500000000
start = Time.now
until i = imax
an = (a/2) + (b/2)
bn = sqrt(a) * sqrt(b)
tn = t - p * ((a-an) * (a-an))
pn = 2 * p
a = an
b = bn
t = tn
p = pn
i +=1
PI = ((a+b)*(a+b))/(4*t)
end
finish = Time.now
time = finish - start
puts PI
puts time
首先不要立即使
i
等于imax
:
until i = imax
应该是
until i == imax
更妙的是,去做吧
500000000.times do
而不是那一行。首先不要使
i
等于imax
:
until i = imax
应该是
until i == imax
更妙的是,去做吧
500000000.times do
而不是那一行。另一件你做错的事是在循环中指定一个常数
PI
。虽然可以重新指定常数,但这样做是不正确的。可以使用变量,也可以将赋值移到循环外部,使其只被赋值一次
即使我删除分配并打印出每次迭代的结果,如下所示:
include Math
a = 1
b = 1/sqrt(2)
t = 0.25
p = 1
i = 0
imax = 500000000
until i == imax
an = (a/2) + (b/2)
bn = sqrt(a) * sqrt(b)
tn = t - p * ((a-an) * (a-an))
pn = 2 * p
a = an
b = bn
t = tn
p = pn
i +=1
puts ((a+b)*(a+b))/(4*t)
end
-2.1244311544725596
-1.1383928808463357
-1.1265990444799223
-1.1265961703346379
-1.126596170334544
-1.126596170334544
... # very long repetition of the same number
-1.126596170334544
-1.126596170334544
NaN
NaN
... # NaN forever
我得到了错误的结果。事情是这样的:
include Math
a = 1
b = 1/sqrt(2)
t = 0.25
p = 1
i = 0
imax = 500000000
until i == imax
an = (a/2) + (b/2)
bn = sqrt(a) * sqrt(b)
tn = t - p * ((a-an) * (a-an))
pn = 2 * p
a = an
b = bn
t = tn
p = pn
i +=1
puts ((a+b)*(a+b))/(4*t)
end
-2.1244311544725596
-1.1383928808463357
-1.1265990444799223
-1.1265961703346379
-1.126596170334544
-1.126596170334544
... # very long repetition of the same number
-1.126596170334544
-1.126596170334544
NaN
NaN
... # NaN forever
您的算法一定有问题。另一个错误是在循环中指定一个常量
PI
。虽然可以重新指定常数,但这样做是不正确的。可以使用变量,也可以将赋值移到循环外部,使其只被赋值一次
即使我删除分配并打印出每次迭代的结果,如下所示:
include Math
a = 1
b = 1/sqrt(2)
t = 0.25
p = 1
i = 0
imax = 500000000
until i == imax
an = (a/2) + (b/2)
bn = sqrt(a) * sqrt(b)
tn = t - p * ((a-an) * (a-an))
pn = 2 * p
a = an
b = bn
t = tn
p = pn
i +=1
puts ((a+b)*(a+b))/(4*t)
end
-2.1244311544725596
-1.1383928808463357
-1.1265990444799223
-1.1265961703346379
-1.126596170334544
-1.126596170334544
... # very long repetition of the same number
-1.126596170334544
-1.126596170334544
NaN
NaN
... # NaN forever
我得到了错误的结果。事情是这样的:
include Math
a = 1
b = 1/sqrt(2)
t = 0.25
p = 1
i = 0
imax = 500000000
until i == imax
an = (a/2) + (b/2)
bn = sqrt(a) * sqrt(b)
tn = t - p * ((a-an) * (a-an))
pn = 2 * p
a = an
b = bn
t = tn
p = pn
i +=1
puts ((a+b)*(a+b))/(4*t)
end
-2.1244311544725596
-1.1383928808463357
-1.1265990444799223
-1.1265961703346379
-1.126596170334544
-1.126596170334544
... # very long repetition of the same number
-1.126596170334544
-1.126596170334544
NaN
NaN
... # NaN forever
你的算法一定有问题。除了@Nick和@sawa提出的问题外,你的算法也有缺陷:a和b的乘积的平方根不等于a和b的平方根的乘积 在ruby中:
include Math
a, b, t, p = 1, 1/sqrt(2), 0.25, 1
imax = 5
imax.times do |i|
an = (a+b) / 2
bn = sqrt(a * b)
tn = t - p * ((a-an) * (a-an))
pn = 2 * p
a, b, t, p = an, bn, tn, pn
pi = ((a+b)*(a+b))/(4*t)
printf "%d : %10.60f\n", i, pi
end
运行此命令可以让我:
0 : 3.140579250522168575088244324433617293834686279296875000000000
1 : 3.141592646213542838751209274050779640674591064453125000000000
2 : 3.141592653589794004176383168669417500495910644531250000000000
3 : 3.141592653589794004176383168669417500495910644531250000000000
4 : 3.141592653589794004176383168669417500495910644531250000000000
很明显,您需要更高的精度,因此需要使用BigDecimal。因为这是你的家庭作业,我将把它留给你:-)。(如果不确定要更改哪些变量,请尝试除
i
和imax
之外的所有变量。同时检查)除了@Nick和@sawa提出的问题,您的算法存在缺陷:a和b的乘积的平方根不等于a和b的平方根的乘积
在ruby中:
include Math
a, b, t, p = 1, 1/sqrt(2), 0.25, 1
imax = 5
imax.times do |i|
an = (a+b) / 2
bn = sqrt(a * b)
tn = t - p * ((a-an) * (a-an))
pn = 2 * p
a, b, t, p = an, bn, tn, pn
pi = ((a+b)*(a+b))/(4*t)
printf "%d : %10.60f\n", i, pi
end
运行此命令可以让我:
0 : 3.140579250522168575088244324433617293834686279296875000000000
1 : 3.141592646213542838751209274050779640674591064453125000000000
2 : 3.141592653589794004176383168669417500495910644531250000000000
3 : 3.141592653589794004176383168669417500495910644531250000000000
4 : 3.141592653589794004176383168669417500495910644531250000000000
很明显,您需要更高的精度,因此需要使用BigDecimal。因为这是你的家庭作业,我将把它留给你:-)。(如果不确定要更改哪些变量,请尝试除
i
和imax
之外的所有变量。同时检查)我不熟悉Ruby和这个内核的睡眠方法。你能告诉我应该编辑什么使它工作吗?我用帕斯卡做了一个程序,需要28秒来迭代500密耳次。此代码在一秒钟内给出答案。所以一定是出了问题。您正在尝试分配PI,但已经有一个PI(include'math'
)给了您。谢谢,它解决了“已初始化常量PI错误”。但我仍然收到警告:Bignum超出浮点范围。有没有办法解决这个问题?浮点数最多可以代表1.7976931348623157e+308。Ruby警告说,它正在使用比这更大的数字进行计算。看一看标准库。我不熟悉Ruby和这个内核#sleep方法。你能告诉我应该编辑什么使它工作吗?我用帕斯卡做了一个程序,需要28秒来迭代500密耳次。此代码在一秒钟内给出答案。所以一定是出了问题。您正在尝试分配PI,但已经有一个PI(include'math'
)给了您。谢谢,它解决了“已初始化常量PI错误”。但我仍然收到警告:Bignum超出浮点范围。有没有办法解决这个问题?浮点数最多可以代表1.7976931348623157e+308。Ruby警告说,它正在使用比这更大的数字进行计算。看看标准库。谢谢你的回答。然而,这两种方法都给出了一个错误:在第12行给出:warning:Bignum超出浮点范围,在第19行给出:warning:ready initialized constant PI。有什么建议吗?谢谢你的回答。然而,这两种方法都给出了一个错误:在第12行给出:warning:Bignum超出浮点范围,在第19行给出:warning:ready initialized constant PI。有什么建议吗?现在OP正在使用Math::PI,循环从不循环。谢谢。但现在我得到了一个错误:警告Bignum超出浮点范围。知道怎么解决吗?Pascal和Ruby不能共享代码(一般来说)。你一定把代码重写成了Ruby。我是说你的翻译肯定是错误的。所以如果我发现它会很好,但我仍然有bignum超出范围的浮点错误。现在OP使用的是Math::PI,循环从不循环。谢谢。但现在我得到了一个错误:警告Bignum超出浮点范围。知道怎么解决吗?Pascal和Ruby不能共享代码(一般来说)。你一定把代码重写成了Ruby。我是说你的翻译肯定是错的。所以,如果我发现它会很好,但我仍然有bignum超出范围的浮点错误。太好了!这对我有用。BigDecimal应该不是问题。谢谢你的回答!伟大的这对我有用。BigDecimal应该不是问题。谢谢你的回答!