Ruby

CodeForces 832 B Petya and Exam

Posted on

比赛时候用c++ 搞了一个小时还没出来,结束后用ruby写了个正则改了两次就过了……

真的是崩溃……

题意:
?替代任意好字符,* 替代任意数目的坏字符

思路:
正则瞎搞

AC Code

good = gets.to_str.chomp
pattern = gets.to_str
key = pattern.strip.gsub("?","["+good+"]").gsub("*","[^"+good+"]*")
rg = Regexp.new("^"+key+"$")

n = gets.to_i
n.times do
    buf = gets.to_str
    if rg =~ buf
        puts "YES"
    else
        puts "NO"
    end
end
Ruby

CodeForces 195 C 上班题

Posted on

别说了,上班题,我比赛用c++ 写了一个半小时,晚上继续用c++写了两个小时,突然跟天海吹牛说,要是我会c++的正则表达式,这道题,妙了!
然后就说可以用脚本语言,我也只能勉为其难的用ruby写了。

推荐一个ruby在线正则表达式检测 网站

语法有些忘了……写的慢了点

题意:
模拟 try catch

思路:
无。

AC Code

#!/usr/bin/env ruby
# encoding: utf-8
n=gets.to_i

thlist = []
thid = []
trylist = []
flag=0

n.times do |id|
  str=gets.strip!
  next if flag == 1
  if /^try$/ =~ str
    trylist << id
  elsif /throw/ =~ str
    /(?<=\()\s*\w+\s*(?=\))/ =~ str
    thlist << $&.strip
    thid << id
  elsif /catch/ =~ str
    /(?<=\()\s*\w+\s*(?=,)/ =~ str
    if (pos=thlist.index($&.strip))!=nil && thid[pos] > trylist.last
      /(?<=\").+(?=\")/ =~ str
      puts $&
      flag=1
    end
    trylist.pop
  end
end

puts "Unhandled Exception" if flag == 0
Ruby

数值计算编程作业(Ruby版)

Posted on

内容包括

  1. 二分法求解二元一次方程的根
  2. 牛顿法求解一元多次方程的根
  3. 顺序消去法解线性方程组
  4. 列选主元消去法解线性方程组
  5. 全选主元消去法解线性方程组
  6. Doolittle分解线性方程组
  7. Crout分解线性方程组
  8. 平方根法求线性方程组
  9. 拉格朗日插值法
  10. 牛顿插值法
  11. 最小二乘法——线性拟合
  12. 变步长梯形求积算法计算积分
  13. 龙贝格算法计算积分
  14. 改进欧拉算法求常微分方程的数值解
  15. 四阶龙格-库塔法求常微分方程的数值解

累!!!!!!!不详细介绍了

#!/usr/bin/env ruby
# encoding: utf-8

$eps=1e-8
$inf=0x3f3f3f3f

class TwoSplit
  def initialize
    @a,@b,@c,@d=2,4,2,18
  end

  def getVal(x)
    @a*x*x+@b*x+@c-@d
  end
  private :getVal

  def three_split
    le,ri,mid=-$inf,$inf,1
    while le+$eps<ri
      mid=(le+ri)/2
      if(getVal(mid)+$eps<0)
        le=mid+$eps
      else
        ri=mid-$eps
      end
    end
    mid
  end
  private :three_split

  def two_split(le,ri)
    mid=1
    while le+$eps<ri
      mid=(le+ri)/2
      if(getVal(mid)<0)
        le=mid+$eps
      else
        ri=mid-$eps
      end
    end
    mid
  end
  private :two_split

  def calculate_ans
    @a,@b,@c,@d=-@a,-@b,-@c,-@d if (@a<0)
    k=three_split
    if(getVal(k)>0)
      puts 'No Answer'
    else
      rans=two_split(k,1.0*$inf)
      lans=2*k-rans
      puts '测试方程为2x^2+4x+2=18'
      printf("方程解为:%.2f\n",lans)
      printf(" %.2f",rans) if((lans-rans).abs>$eps*10)
      puts ''
    end
  end
end

class NewtonIterate
  def initialize
    @a,@b,@c,@d=-2,-5,1,3
  end

  def get_val(x)
    @a*x*x+@b*x+@c-@d
  end

  def get_der(x)
    2*@a*x+@b
  end

  def newton(val)
    pre=val
    val=pre-get_val(pre)/get_der(pre)
    while((pre-val).abs>$eps)
      pre=val
      val=pre-get_val(pre)/get_der(pre)
    end
    val
  end

  def calculate_ans
    if(@b*@b-4*@a*@c<0)
      puts 'No Answer'
    else
      lans=newton(-1.0*$inf)
      rans=newton(1.0*$inf)
      puts '求解方程为-2x^2-5x+1=3'
      printf("方程解为:%.2f",lans);
      printf(" %.2f",rans) if((lans-rans).abs>$eps)
      puts ''
    end
  end
end

class ResolveMat
  def initialize
    @mat=6.times.map{ [0] * 6 }
    @l=6.times.map{ [0] * 6 }
    @u=6.times.map{ [0] * 6 }
    @x,@y=[0]*6,[0]*6
    @b=[1,2,3,4]
    @mat[0]=[2,10,4,-3]
    @mat[1]=[-3,-4,-12,13]
    @mat[2]=[1,2,6,-4]
    @mat[3]=[4,14,9,-13]
    @n=4
  end

  def print_mat(mat)
    yield
    @n.times do |i|
      print '['
      @n.times do |j|
        if((mat[i][j]-0).abs > $eps)
          printf("%8.3f ", mat[i][j]);
        else
          printf("         ");
        end
      end
      puts ']'
    end
    puts ''
  end

  def doolittle
    @n.times { |i| @l[i][i]=1 }

    @n.times do |k|
      k.upto(@n-1) do |j|
        @u[k][j]=@mat[k][j]
        k.times { |i| @u[k][j]-=(@l[k][i]*@u[i][j]) }
      end

      (k+1).upto(@n-1) do |i|
        @l[i][k]=@mat[i][k]
        k.times { |j| @l[i][k]-=(@l[i][j]*@u[j][k]) }
        @l[i][k]/=1.0*@u[k][k]
      end
    end

    @n.times do |i|
      @y[i]=@b[i]
      i.times { |j| @y[i]-=(@l[i][j]*@y[j]) }
    end

    (@n-1).downto(0) do |i|
      @x[i]=@y[i]
      (i+1).upto(@n-1) { |j| @x[i]-=(@u[i][j]*@x[j]) }
      @x[i]/=1.0*@u[i][i]
    end
    puts 'Doolittle分解矩阵'
    print_mat(@mat) {puts '原矩阵为:'}
    print_mat(@l) {puts '矩阵L为:'}
    print_mat(@u) {puts '矩阵U为:'}
  end

  def crout
    @n.times { |i| @u[i][i]=1 }

    @n.times do |k|
      k.upto(@n-1) do |i|
        @l[i][k]=@mat[i][k]
        k.times { |j| @l[i][k]-=(@l[i][j]*@u[j][k]) }
      end
      (k+1).upto(@n-1) do |i|
        @u[k][i]=@mat[k][i]
        k.times { |j| @u[k][i]-=(@l[k][j]*@u[j][i]) }
        @u[k][i]/=1.0*@l[k][k]
      end
    end

    @n.times do |i|
      @y[i]=@b[i]
      i.times { |j| @y[i]-=(@l[i][j]*@y[j]) }
      @y[i]/=1.0*@l[i][i]
    end
    (@n-1).downto(0) do |i|
      @x[i]=@y[i]
      (i+1).upto(@n-1) { |j| @x[i]-=(@u[i][j]*@x[j]) }
      # @x[i]/=@u[i][i]
    end
    puts 'Crout分解矩阵'
    print_mat(@mat) {puts '原矩阵为:'}
    print_mat(@l) {puts '矩阵L为:'}
    print_mat(@u) {puts '矩阵U为:'}
  end

  def square #待验证
    t=6.times.map { [0]*6 }
    lt=6.times.map { [0]*6 }
    d=6.times.map { [0]*6 }

    @n.times { |i| lt[i][i]=1 }
    t[0][0]=@mat[0][0]

    1.upto(@n-1) do |i|
      t[i][0] = @mat[i][0]
      lt[0][i] = @mat[0][i] / t[0][0]
    end

    1.upto(@n-1) do |i|
      1.upto(i) do |j|
        t[i][0]=@mat[i][0]
        j.times { |k| t[i][j]-=t[i][k]*lt[k][j] }
      end

      (i+1).upto(@n-1) do |j|
        lt[i][j] = @mat[i][j]
        i.times {|k| lt[i][j] = lt[i][j] - t[i][k] * lt[k][j] }
        lt[i][j] = lt[i][j] / t[i][i]
      end
    end

    @n.times do |i|
       @n.times do |j|
         @l[i][j]=lt[i][j]
         d[i][j]=0 if i!=j
         d[i][j]=t[i][j] if i==j
       end
    end

    @y[0]=@b[0]
    1.upto(@n-1) do |i|
      i.times.reduce(0.0) { |sum,k| @y[i]= @b[i]-(sum+=lt[k][i]*@y[k]) }
      # m=0.0
    end

    @x[@n-1]=@y[@n-1]/t[@n-1][@n-1]
    (@n-1).downto(0) do |i|
      (i+1).upto(@n-1).reduce(0.0)  { |sum,k|  @x[i]=@y[i]/d[i][i] - (sum+=lt[i][k]*@x[k]) }
    end

    print_mat(@mat) { puts '所要求解的线性方程为:'}
    @n.times { |i| printf("x[%d]=%.3f \n", i+1, @x[i]); }
  end
end

class Order

  def initialize
    @mat = Array.new(4,[])
    @mat[1]=[0,1,2,3,1]
    @mat[2]=[0,5,4,10,0]
    @mat[3]=[0,3,-0.1,1,2]
    @n=3
  end

  def print_mat
    yield
    @n.times do | i |
      (@n+1).times do | j |
        printf("%.2f ",@mat[i+1][j+1])
      end
      puts ''
    end
  end
  private :print_mat

  def print_ans
    print "解为:"
    @n.times do | k |
      printf("%.2f ",@mat[k+1][@n+1])
    end
    printf "\n\n"
  end
  private :print_ans

  def calculate_answer
    @mat[@n][@n+1] /= @mat[@n][@n]
    (@n-1).downto(1) do |i|
      @mat[i][@n+1]-=(i+1..@n).reduce(0) {|sum,j| sum+=@mat[i][j]*@mat[j][@n+1]}
    end
  end
  private :calculate_answer

  def calculate_mat(i)
    (i+1).upto(@n+1) do | j |
      @mat[i][j]/=(1.0*@mat[i][i])
    end
    @mat[i][i]=1
    (i+1).upto(@n) do | k |
      (i+1).upto(@n+1) do | j |
        @mat[k][j]-=@mat[k][i]*@mat[i][j]
      end
    end
  end
  private :calculate_mat

  def original_order
    print_mat {puts "顺序消去法:\n原矩阵为:"}
    1.upto(@n-1) do | i |
      calculate_mat(i)
    end
    print_mat {puts '所得上三角矩阵为:'}
    calculate_answer
    print_ans
  end

  def col_order
    print_mat {puts "列主元素消去法:\n原矩阵为:"}
    1.upto(@n-1) do | i |
      now,maxx=i,@mat[i][i]
      (i+1).upto(@n) do | j |
        if(@mat[j][i]>maxx)
          maxx,now=@mat[j][i],j
        end
      end

      if i!=now
        (i..@n+1).each do | k |
         @mat[i][k],@mat[now][k] = @mat[now][k],@mat[i][k]
        end
      end
    calculate_mat(i)
    end
    print_mat {puts '所得上三角矩阵为:'}
    calculate_answer
    print_ans
  end

  def all_order
    print_mat {puts "全主元素消去法:\n原矩阵为:"}
    1.upto(@n-1) do | i |
      nx,ny,maxx=i,i,@mat[i][i]

      i.upto(@n) do | j |
        i.upto(@n) do | t |
          if(@mat[j][t]>maxx)
            maxx,nx,ny=@mat[j][t],j,t
          end
        end
      end

      if i!=nx #row exchange
        i.upto(@n+1) do | k |
          @mat[i][k],@mat[nx][k] = @mat[nx][k],@mat[i][k]
        end
      end

      if i!=ny # col exchange
        i.upto(@n) do | k |
          @mat[k][i],@mat[k][ny] = @mat[k][ny],@mat[k][i]
        end
      end

      calculate_mat(i)
    end
    print_mat {puts '所得上三角矩阵为:'}
    calculate_answer
    print_ans
  end

end

class VarStep
  def initialize
    @val = (1 + getVal(1))/2
    @pre,@n = 0x3f3f3f3f,1
  end

  def getVal(x)
    Math.sin(x) / x
  end

  def func(n,pre)
    sum,x = 0.0,0
    n.times do
      x = x + 1.0/(2*n)
      sum = sum + getVal(x)
      x = x + 1.0/(2*n)
    end
    @pre/2.0 + sum/(2*n)
  end

  def calculate_ans
    while (@val-@pre).abs > $eps
      @pre = @val
      @val = func(@n,@val)
      @n*=2
    end
    puts '积分函数为sin(x)/x,积分区间为[0,1]'
    printf("积分结果为%.8f\n",@val)
  end

end

class FourthRomberg
  def initialize
    @a,@b,@n=1,5,5
    @x,@y,@k=[],[],[]
    @h=1.0*(@b-@a)/@n
    @x[0],@y[0]=@a,17
  end

  def der_func(x,y)
    x-y+1
  end
  private :der_func

  def calculate_ans
    1.upto(@n) do |i|
      @x[i-1]=@x[0]+(i-1)*@h
      h1=@h/2.0
      @k[1]=der_func(@x[i-1],@y[i-1])
      @k[2]=der_func(@x[i-1]+h1,@y[i-1]+h1*@k[1])
      @k[3]=der_func(@x[i-1]+h1,@y[i-1]+h1*@k[2])
      @k[4]=der_func(@x[i-1]+@h,@y[i-1]+@h*@k[3])
      @y[i]=@y[i-1]+@h*(@k[1]+2*@k[2]+2*@k[3]+@k[4])/6.0
    end

    puts "a=1,b=5\nn=5\ny0=17\nf(x)=x-y+1\n"
    @n.times do |i|
      printf("y[%d]: %.2f\n",i+1,@y[i+1])
    end
  end
end

class ImproveEuler
  def initialize
    @up,@down,@n = 0.5,0,5
    @h = (@up-@down) / @n
    @xn = @down
    @yn = 1
  end

  def der_func(x,y)
    x - y + 1
  end

  def calculate_ans
    print "f(x,y)=x-y+1\n积分区间为[0,0.5]\ny0=1\n区间5等分\n"
    @n.times do | i |
      xl = @xn + @h
      ylb = @yn + @h * der_func(@xn,@yn)
      yl = @yn + @h / 2 * (der_func(@xn,@yn)+der_func(xl,ylb))
      printf("x%d=%f,y%d=%f\n", i, xl, i, yl)
      @xn,@yn = xl,yl
    end
  end
end

class Lagrance
  def initialize
    @n,@m,@ans=2,195,0
    @x=[121,144,100]
    @y=[11,12,10]
  end

  def calculate_ans
    0.upto(@n) do |i|
      key=1.0*@y[i]
      0.upto(@n) do |j|
        next if(i==j)
        key*=(1.0*(@m-@x[j])/(@x[i]-@x[j]))
      end
      @ans+=key
    end
    puts '给定3个坐标:'
    puts 'x[0]:121,y[0]:11'
    puts 'x[1]:144,y[1]:12'
    puts 'x[2]:100,y[2]:10'
    printf("询问195的y值为%.2f\n",@ans)
  end
end

class NewtonInterpolate
  def initialize
    @n=4
    @form=[0.0]*6
    @x=[10,9,3,11,2]
    @y=[100,80,9,123,4]
  end

  def calculate_ans
    @n.times { |i| @form[i]=@y[i] }
    (@n+1).times do |i|
      @n.downto(i+1) { |j| @form[j] = (@form[j]-@form[j - 1]) / (@x[j] - @x[j - 1 - i]) }
    end
    tmp,hx=1,6.42
    newton=@form[0]
    @n.times do |i|
      tmp*=(hx-@x[i])
      newton+=tmp*@form[i+1]
    end
    @n.times { |i| printf("第%d个点%.2f %.2f\n",i+1,@x[i],@y[i]) }
    printf("F(%.2f) = %.2f\n", hx, newton)
  end
end

class LeastSquare
  def initialize
    @x=[10,9,5,6,2]
    @y=[99,81,24,37,4]
    @a,@b=0.0,0.0
    @n=5
  end

  def get_val(x)
    @a*x+@b
  end

  def calculate_ans
    t=[0.0]*4
    @n.times do |i|
      t[0]+=@x[i]*@x[i]
      t[1]+=@x[i]
      t[2]+=@x[i]*@y[i]
      t[3]+=@y[i]
    end
    @a=(t[2]*@n-t[1]*t[3])/(t[0]*@n-t[1]*t[1])
    @b=(t[0]*t[3]-t[1]*t[2])/(t[0]*@n-t[1]*t[1])
    printf("所得函数为%dx%d\n",@a,@b)
    puts '测试数:12'
    puts get_val(12)
  end
end

class Romberg
  @@pi=4.0*Math.atan(1.0)
  def initialize
    @a,@b=0.000001,1.0
    @n,@h=20,Float(@b-@a)
    @t=20.times.map{ [0] * 2 }
    @t[0][1]=trapezium
    @n*=2
  end

  def get_val(x)
    Math.sin(x)/x
  end
  private :get_val

  def trapezium
    @h=(@b-@a)/@n
    sum = 1.upto(@n-1).reduce(0.0) {|tmp,i| tmp+=get_val(@a+i*@h) }
    sum+=(get_val(@a)+get_val(@b))/2.0
    @h*sum
  end

  def calculate_ans

    puts 'sin(x)/x在[0,1]区间内的积分测试:'
    (1..9).each do |m|
      m.times { |i| @t[i][0]=@t[i][1] }
      @t[0][1]=trapezium
      @n*=2
      m.times do |i|
        @t[i+1][1]=@t[i][1]+(@t[i][1]-@t[i][0]) / ((4**m)-1)
      end
      if (@t[m-1][1]-@t[m][1]).abs < $eps
        printf("计算的数为:%.6f\n", @t[m][1])
        return @t[m][1]
      end
    end
    puts 'No Answer'
  end
end

def nodekey
  while true
    puts '<===================================>'
    puts '1.二分法求解二元一次方程的根'
    puts '2.牛顿法求解一元多次方程的根'
    puts '3.顺序去法解线性方程组'
    puts '4.列选主元消去法解线性方程组'
    puts '5.全选主元消去法解线性方程组'
    puts '6.Doolittle分解线性方程组'
    puts '7.Crout分解线性方程组'
    puts '8.平方根法求线性方程组'
    puts '9.拉格朗日插值法'
    puts '10.牛顿插值法'
    puts '11.最小二乘法——线性拟合'
    puts '12.变步长梯形求积算法计算积分'
    puts '13.龙贝格算法计算积分'
    puts '14.改进欧拉算法求常微分方程的数值解'
    puts '15.四阶龙格-库塔法求常微分方程的数值解'
    puts ' 0.退出'
    puts '<====================================>'
    print "请选择你要选择的操作:"
    op=gets.to_i
    case op
      when 0
        break
      when 1
        TwoSplit.new.calculate_ans
      when 2
        NewtonIterate.new.calculate_ans
      when 3
        Order.new.original_order
      when 4
        Order.new.col_order
      when 5
        Order.new.all_order
      when 6
        ResolveMat.new.doolittle
      when 7
        ResolveMat.new.crout
      when 8
        ResolveMat.new.square
      when 9
        Lagrance.new.calculate_ans
      when 10
        NewtonInterpolate.new.calculate_ans
      when 11
        LeastSquare.new.calculate_ans
      when 12
        VarStep.new.calculate_ans
      when 13
        Romberg.new.calculate_ans
      when 14
        ImproveEuler.new.calculate_ans
      when 15
        FourthRomberg.new.calculate_ans
      else
        puts '请输入0-15的选项,选择0为退出'
    end
  end
end

nodekey
Ruby

以Ruby为例浅谈动态语言的赋值机制

Posted on
  1. 问题提出
  2. 结论
  3. 数组解释
  4. 数字解释 1
  5. 数字解释 2
  6. 对该特性的思考
  7. Ruby与Python的内存管理机制
1.问题提出

最近的数值计算实验纠结了一下最后想用Ruby解决,结果在中途发现了这样的一个问题。

定义一个二维数组ary,我先是给 ary[0][0]赋值为 1,再是给 ary[1][0]赋值为 233,结果输出 ary[0][0] 居然为 233,输出整个ary ,发现每个数组第一项都是 233 。

详细介绍的可以看我在Ruby China发的帖子

2.结论

在这里我以Ruby为例详细介绍一下动态语言的赋值机制。

首先我们先明确几点:
1. 在ruby中参数的传递永远都是引用。
2. 每一个变量保存的都是对对象的引用。
3. 我们访问对象都是通过引用间接访问的。

3.数组解释

这该如何理解呢?以我上面那个Array.new(6,Array.new(6,0))来说,ruby先执行里表达式,创建一个Array对象并返回其引用 设为α;然后执行,外Array.new,创建6个对 α 的引用,就是对引用的引用,但最后还是引用自对象。因此ary的6个对象都为引用,如果我改变这个对象的值,那么ary的6个引用都将随之改变。

那么如果我要定义一个数组,并初始化其中几个值又应该怎么做呢。

当然是去从本质上解决问题啊。答案应该是将后一个Array.new通过块传入:

Arrar.new(6) { Array.new(6,0) }

假设你拥有block的知识,在 6 次Array.new 的每个块中,都会执行一次 Array.new(6,0)并返回这个Array.new的引用,就会得到6个不相同的对象。简单说,通过block传参,block中的代码每次都会被重新执行一遍。而直接传参就只会将参数的引用传递过来。

4.数字解释 1

解决了数组问题,再来解释一下最平常不过的数字。先贴上我的理解来源,并向大佬表示感谢。

def pref3(a)
  a = 5
  a.object_id
end

a = 1
a.object_id #输出3

pref3(a) #输出11
puts a 

这段代码很容易陷入怀疑 在ruby中参数的传递永远都是引用 正确性的误区:
“如果我传递的是引用,那么我在函数内部发生的变化理应对外部也产生影响呀,为什么输出仍然是1呢??”

在这里,经过 pref3 的调用, a仍然会是 3 ,然而在函数内和函数外的 object_id 却是不同的。这很显然,我们会很自然地去认为,这两个 a 所引用的并不是同一个对象,而实际上也是如此。

现在让我们来重新理解一下Ruby的赋值机制。它大致分为两个步骤:
1. 根据右值创建对象并返回该对象的引用。
2. 不论左值是否为空,左值所引用的对象又是什么类型,右值的引用都会将其覆盖。

也就是说在函数体 pref3 中的 a 初始是 ==对象 1== 的引用,而在执行 a = 5 时,ruby会先创建一个==对象 5== , 并使其引用覆盖掉 a 的原引用对象 ==对象 1==。
至此,一切都理论都得以成立。

5.数字解释 2

再试着来理解一下这段代码

def pref3(a,b)
  a,b = b,a
end

a,b = 1,2
pref3(a,b)
puts a,b #输出 1,2

根据上述,每一个变量保存的都是对 对象的引用,那么在 pref3 中,a,b,其实是对函数外 a,b的引用,即==对象 1和对象 2==引用的引用,通过递归仍然是对==对象 1和对象 2==的引用。
而在此我交换 a,b 实质上是把,b的对象引用覆盖给了a,a的对象引用覆盖给了b,而函数中的两个变量 a,b ,因为其本身是局部变量,且为引用,引用之间的交换并不会对函数外的对象引用产生任何影响,更不会对所引用对象产生任何影响。

于是乎,结果仍然是

1,2

6. 对该特性的思考

总的来说,这个赋值机制还是比较方便的,比较纯粹的。我本人就比较喜欢纯粹的事物,Linux下一切皆文件,Ruby下一切皆对象,动态语言下一切变量皆引用,一切问题皆网络流!!

但是,在我突然意识到,如果我的理论一切都完美成立的话,就会发生内存上的问题。因为我们在创建对象的时候返回的是其引用,我们根本无法直接访问到它,更别谈什么主动释放了。

为什么我想主动释放呢,也许我们对一些特殊的变量一申请,一创建,就会从头用到尾,但是Ruby下一切皆对象,对于数字和字符串这些频繁使用的对象来说,不释放空间非常容易产生内存问题。

然而睡了个觉,回头一想,突然想起了Programming Ruby中关于内存释放有一个自己的机制:
ruby在每次创建变量,传递参数的时候都会对被引用次数进行计数,如果这个被引用次数变为0了,就会自动被释放。这个机制实在是妙哉!!

一想到这,我想我跟松本弘行应该是想到一块去了。蛤蛤蛤!


updated time : May 16

6. Ruby与Python的内存管理机制

自己YY就以为这个问题解决了,没想到被大佬指出了错误,真的是醍醐灌顶。

引用计数这种内存管理机制是地的确确存在的,并且是python所使用的,但Ruby用的是另外一种管理机制 mark and sweep。
首先献给处大佬给我学习的 博文 ,并对大佬和作者表示感谢,然而这篇文章,主要针对的还是小白,如果用来复习就有点得不偿失了。所以我这里简单说一下个人理解,如果与原博文有任何冲突,一切以原博文为主。

Ruby:
预先创建一个空闲链表,一旦有 new 申请就直接从里面拿取空间,如果链表空间不够,则停止其他所有程序活动,不断迭代所有对象的引用,对 所得到的链表内部对象 进行标记,最后遍历链表,清理未标记内存,将其重新构建成一个新的空闲链表。
更深的,基于弱代假说:

年亲的对象通常死得快,而老对象则很有可能存活更长的时间。

对一次 sweep 后被标记的对象,就会被Ruby划分为成熟对象,并在之后很长一段时间内,打赌他们不会再被取消标记。也就是说这些对象 ruby 在很长一段时间内将不会去遍历判断。
而当成熟对象的数目双倍于上次全局回收的数目时,Ruby会清理所有的标记并将所有的对象都视为新对象以重新清理。

Python:
python采取引用标记机制,因为互相引用的情况存在,python不得不用上了类似与ruby的方法,建立一个引用链表称为0代链表,如果内存空间达到阈值就对链表内部进行 对循环引用的检测。其中,存留下来的转移至 1代链表 ,同理会转移至 2代链表(最多2代)。虽然都是转移,但是阈值显然是不同的,对于 0 代链表的操作显然要活跃一些,所以阈值应该是要低一些(猜测,原文中并没有说……)。然而对 2代链表之后的事情我就不清楚了……

然而说到底,这些都是博主说的,是否正确我也无法证实,但是看上去貌似灰常有道理。如果要深入研究,到头来还是得看源码……