查看: 2171|回复: 2

[通用发布] Ruby:解非齐次线性方程(组)机(MacSNEL)

[复制链接]
梦石
0
星屑
1944
在线时间
404 小时
注册时间
2015-8-30
回帖
322
发表于 2016-8-27 17:16:00 | 显示全部楼层 |阅读模式

加入我们,或者,欢迎回来。

您需要 登录 才可以下载或查看,没有账号?注册会员

×
本帖最后由 有丘直方 于 2016-8-28 20:06 编辑


前言

最近不想钻研RGSS(主要因为没电脑),钻研钻研Ruby。
此前有电脑的时候在ruby-lang官网找到一个Ruby2.4.0的安装包。哇噻,最让我开心的是从这个版本开始Integer没有子类了!Fixnum和Bignum合并了!
结果不知道是不是因为电脑的问题,这个Ruby根本就没法用啊……连最简单的
  1. print("Hello, World!")
复制代码
都运行不了。
电脑被我妈没收之后(坑啊,我就研究一下RGSS嘛,干吗没收),我的Dell电脑退化成iPad和Redmi了。Android系统都没有一个好用的Ruby,不过iOS系统的App Store里面有一个叫做“rubyi”的软件,有一个免费版本和两个收费版本。
我当然用免费版本了,因为我根本就不知道付款密码是什么,再说我也不知道我爸的银行卡有没有足够的钱,我爸也不会同意给我钱,我妈也不会支持我研究Ruby的。免费版本的这个软件有一坨广告,而且代码长了之后容易闪退。不过没关系,它会帮我自动保存文件闪退就没什么大不了的,广告也不会挡住关键信息,所以还是挺好用的。我还想看一下这个软件的Ruby版本是多少,但是我发现当我执行
  1. p(RUBY_VERSION)
复制代码
时它会报错说找不到这个常量……
但是这并不妨碍我制作出了解非齐次线性方程(组)机。



简介

解非齐次线性方程(组)机,Machine Solving Nonhomogeneous Linear Equation(s),简称MacSNEL。MacSNEL是我制作的用于解非齐次线性方程(组)的程序。
非齐次线性方程(组)是指常数项不全为0且方程数量和未知数数量相等的未知数最高次数为1的整式方程(组)。使用者可以在输入未知数数量、系数和常数项之后得到方程(组)的解。
MacSNEL的工作原理是Cramer法则。根据该法则,任意的非齐次线性方程(组)的解都可以表示为两个行列式的商。所以,在使用MacSNEL前应当require行列式类(Determinant)的定义。
参考资料:
非齐次线性方程(组):http://baike.baidu.com/view/1569245.htm;
Cramer法则:http://baike.baidu.com/view/1130618.htm;
行列式类:https://rpg.blue/forum.php?mod=viewthread&tid=395752。



代码

[fold=MacSNEL][pre lang="ruby"]loop do
    begin
        print(@simple ? "================================\n    这是MacSNLE!\n\n" : "    这是“解非齐次线性方程(组)机(Machine Solving Nonhomogeneous Linear Equation(s))”(简称“MacSNLE”)!\n\n")
        @simple = true
        print("    请输入方程(组)的未知数数量;退出程序请输入“0”;阅读简介请输入“-1”:\n")
        unknown = gets.to_i
        if unknown == 0 then exit
        elsif unknown == -1
            print("\n    MacSNEL是有丘直方制作的用于解非齐次线性方程(组)的程序。\n    非齐次线性方程(组)是指常数项不全为0且方程数量和未知数数量相等的未知数最高次数为1的整式方程(组)。使用者可以在输入未知数数量、系数和常数项之后得到方程(组)的解。\n    MacSNEL的工作原理是Cramer法则。根据该法则,任意的非齐次线性方程(组)的解都可以表示为两个行列式的商。所以,在使用MacSNEL前应当require行列式类(Determinant)的定义。\n\n    参考资料:\n    非齐次线性方程(组):http://baike.baidu.com/view/1569245.htm;\n    Cramer法则:http://baike.baidu.com/view/1130618.htm;\n    行列式类:https://rpg.blue/forum.php?mod=viewthread&tid=395752。\n\n\n")
            next
        end
        print("\n    ax = b\n\n    a1x + b1y = c1\n    a2x + b2y = c2\n\n    a1x + b1y + c1z = d1\n    a2x + b2y + c2z = d2\n    a3x + b3y + c3z = d3\n\n    ……\n\n    请把系数和常数项的值按顺序放入方括号“[]”中并用逗号“,”隔开;退出程序请输入“0”:\n")
        ary = eval(gets)
        exit if ary == 0
        row = [[]] * (ary.size / (unknown + 1))
        for i in 0...(ary.size / (unknown + 1))
            row = ary[i * (unknown + 1), unknown + 1].to_f
        end
        row_basic = row.clone
        for i in 0...row_basic.size
            row_basic = row.clone
            row_basic.delete_at(@unknown)
        end
        @det_basic = Determinant.new(row_basic)
        ary = []
        for i in 0...row.size
            ary << row[-1].to_f
        end
        for i in 1..unknown
            row_basic = row.clone
            for j in 0...row_basic.size
                row_basic[j] = row[j].clone
                row_basic[j].delete_at(unknown)
            end
            eval("@det_#{i} = Determinant.new(row_basic).change_y(i - 1, ary)")
        end
        result = [0] * unknown
        for i in 0...result.size
            result = eval("@det_#{i + 1}").value / @det_basic.value.to_f
        end
        print("\n    解为#{result}。\n\n    谢谢使用MacSNEL!\n\n\n")
    rescue
        print("\n    非法的输入!\n\n\n")
        next
    end
end[/pre][/fold][fold=Determinant]请把关于行列式类的定义的代码复制到MacSNEL的内容之前。https://rpg.blue/forum.php?mod=viewthread&tid=395752[pre lang="ruby"]#----------------------------------------------------------------
# ### Determinant
#----------------------------------------------------------------
#     行列式类。用于计算、处理、表达行列式的类。
#----------------------------------------------------------------
class Determinant <
#----------------------------------------------------------------
# ## 超类
#----------------------------------------------------------------
#     Object
#----------------------------------------------------------------
Object
#----------------------------------------------------------------
# ## 包含的模块
#----------------------------------------------------------------
#     Comparable
#----------------------------------------------------------------
include(Comparable)
#----------------------------------------------------------------
# ## 类方法
#----------------------------------------------------------------
    class << self
#----------------------------------------------------------------
# # Determinant.new(rows)
#----------------------------------------------------------------
#     生成一个与rows内容相同的行列式。
#     rows是一个嵌套数组,且rows内的数组的长度应与rows的长度相等,否则会引
# 发TypeError。
#----------------------------------------------------------------
        def new(rows)
            super(rows)
        end
    end
#----------------------------------------------------------------
# ## 方法
#----------------------------------------------------------------
#----------------------------------------------------------------
# # size
#----------------------------------------------------------------
#     返回行列式的阶数。
#----------------------------------------------------------------
    def size
        return rows.size
    end
#----------------------------------------------------------------
# # order
#----------------------------------------------------------------
#     同size。
#----------------------------------------------------------------
    def order
        return size
    end
#----------------------------------------------------------------
# # cofactor(x, y)
#----------------------------------------------------------------
#     返回在x、y位置的余子式。
#----------------------------------------------------------------
    def cofactor(x, y)
        ary = rows.clone
        ary.delete_at(x)
        for i in 0...(order - 1)
            ary = i >= x ? rows.clone : rows[i + 1].clone
            ary.delete_at(y)
        end
        return Determinant.new(ary)
    end
#----------------------------------------------------------------
# # cof(x, y)
#----------------------------------------------------------------
#     同cofactor。
#----------------------------------------------------------------
    def cof(x, y)
        return cofactor(x, y)
    end
#----------------------------------------------------------------
# # algebraic_cofactor(x, y)
#----------------------------------------------------------------
#     返回在x、y位置的代数余子式。
#----------------------------------------------------------------
    def algebraic_cofactor(x, y)
        return (-1) ** (x + y) * cofactor(x, y).value
    end
#----------------------------------------------------------------
# # alc(x, y)
#----------------------------------------------------------------
#     同algebraic_cofactor。
#----------------------------------------------------------------
    def alc(x, y)
        return algebraic_cofactor(x, y)
    end
#----------------------------------------------------------------
# # at(x, y)
#----------------------------------------------------------------
#     返回在x、y位置的元素。
#----------------------------------------------------------------
    def at(x, y)
        return rows[x][y]
    end
#----------------------------------------------------------------
# # self[x, y]
#----------------------------------------------------------------
#     同at。
#----------------------------------------------------------------
    def [](x, y)
        return at(x, y)
    end
#----------------------------------------------------------------
# # self[x, y] = val
#----------------------------------------------------------------
#     为在x、y位置的元素赋值代入val。
#     返回val。
#----------------------------------------------------------------
    def []=(x, y, val)
        return rows[x][y] = val
    end
#----------------------------------------------------------------
# # rows = val
#----------------------------------------------------------------
#     为rows赋值代入val。
#     返回val。
#----------------------------------------------------------------
    def rows=(val)
        raise(TypeError) if !val.is_a?(Array)
        for i in val
            raise(TypeError) if !i.is_a?(Array) or i.size != val.size
        end
        return @rows = val
    end
#----------------------------------------------------------------
# # row(x)
#----------------------------------------------------------------
#     返回与第x行内容相同的数组。
#     请参考column。
#----------------------------------------------------------------
    def row(x)
        return rows[x]
    end
#----------------------------------------------------------------
# # column(y)
#----------------------------------------------------------------
#     返回与第y列内容相同的数组。
#     请参考row。
#----------------------------------------------------------------
    def column(y)
        ary = []
        for i in rows
            ary += i[y].to_a
        end
        return ary
    end
#----------------------------------------------------------------
# # change_row(x, ary)
#----------------------------------------------------------------
#     把第x行的内容代替为数组ary的内容。返回self。
#     ary的元素的数量必须与行列式的阶数相等,否则会引发TypeError。
#     请参考change_column。
#----------------------------------------------------------------
    def change_row(x, ary)
        rows[x] = ary
        return self
    end
#----------------------------------------------------------------
# # change_column(y, ary)
#----------------------------------------------------------------
#     把第y列的内容代替为数组ary的内容。返回self。
#     ary的元素的数量必须与行列式的阶数相等,否则会引发TypeError。
#     请参考change_row。
#----------------------------------------------------------------
    def change_column(y, ary)
        for i in 0...size
            rows[y] = ary
        end
        return self
    end
#----------------------------------------------------------------
# # transpose
#----------------------------------------------------------------
#     转置变换。指把行列式逆时针旋转1/4圈。返回self。
#     行列式的性质1:行列式转置后,其值不变(请参考value)。
#----------------------------------------------------------------
    def transpose
        det = self
        for i in 0...size
            change_column(i, det.row(i))
        end
        return self
    end
#----------------------------------------------------------------
# # exchange_row(x, x_ed)
#----------------------------------------------------------------
#     换法变换。指把第x行与第x_ed行的位置互换。返回self。
#     行列式的性质2:互换行列式的两行(列),行列式变号(请参考value)。
#     请参考exchange_column。
#----------------------------------------------------------------
    def exchange_row(x, x_ed)
        a = row(x)
        b = row(x_ed)
        change_row(x, b)
        change_row(x_ed, a)
        return self
    end
#----------------------------------------------------------------
# # exchange_column(y, y_ed)
#----------------------------------------------------------------
#     换法变换。指把第y列与第y_ed列的位置互换。返回self。
#     请参考exchange_row。
#----------------------------------------------------------------
    def exchange_column(y, y_ed)
        a = column(y)
        b = column(x_ed)
        change_column(y, b)
        change_column(y_ed, a)
        return self
    end
#----------------------------------------------------------------
# # multiply_row(x, num)
#----------------------------------------------------------------
#     倍法变换。指把第x行的每一个元素都乘num。返回self。
#     行列式的性质3:行列式的某一行(列)的所有元素都乘k,等同于用k乘这个行
# 列式(请参考value)。
#     请参考multiply_column。
#----------------------------------------------------------------
    def multiply_row(x, num)
        for i in 0...size
            self[x, i] *= num
        end
        return self
    end
#----------------------------------------------------------------
# # multiply_column(y, num)
#----------------------------------------------------------------
#     倍法变换。指把第y列的每一个元素都乘num。返回self。
#     请参考multiply_row。
#----------------------------------------------------------------
    def multiply_column(y, num)
        for i in 0...size
            self[i, y] *= num
        end
        return self
    end
#----------------------------------------------------------------
# # transform_row(x, x_ed, num)
#----------------------------------------------------------------
#     消法变换。指把第x行的每一个元素都加上第x_ed行的对应元素乘num的积。返
# 回self。
#     行列式的性质5:把行列式的某一行(列)的元素都乘k后加到另一行(列)的对
# 应元素上去,行列式的值不变(请参考value)。
#     (行列式的性质4:如果行列式的某一行(列)的元素都是多项式,就可以把该
# 行列式拆成多个行列式的和(请参考value)。)
#     请参考transform_column。
#----------------------------------------------------------------
    def transform_row(x, x_ed, num)
        raise(TypeError) if x == x_ed or x >= size or x_ed >= size
        for i in 0...size
            self[x, i] += row(x_ed) * num
        end
        return self
    end
#----------------------------------------------------------------
# # transform_column(y, y_ed, num)
#----------------------------------------------------------------
#     消法变换。指把第x行的每一个元素都加上第x_ed行的对应元素乘num的积。返
# 回self。
#     请参考transform_row。
#----------------------------------------------------------------
    def transform_column(y, y_ed, num)
        raise(TypeError) if y == y_ed or y >= size or y_ed >= size
        for i in 0...size
            self[i, y] += y(y_ed) * num
        end
        return self
    end
#----------------------------------------------------------------
# # value(expand_calculate = false)
#----------------------------------------------------------------
#     返回行列式的值。当expand_calculate为true时计算时间较长但没有任何误
# 差,为false时计算时间较短但在阶数较大时会有细微误差。
#     若行列式中没有浮点数则返回整数,否则返回浮点数。
#----------------------------------------------------------------
    def value(expand_calculate = false)
        f = false
        for i in 0...size
            for j in 0...size
                if at(i, j).is_a?(Float)
                    f = true
                break
            end
            break if f == true
        end
        if expand_calculate
            if order == 1
                return at(0, 0)
            else
                val = 0
                for i in 0...order
                    val += at(0, i) * algebraic_cofactor(0, i)
                end
            end
        else
            det = self.dup
            for i in 0...size
                j = 0
                i.times do
                    if at(j, j) == 0
                        return 0.0 if f
                        return 0
                    end
                    det.transform_row(i, j, -(at(i, j) / at(j, j).to_f))
                    j += 1
                end
            end
            val = 1
            for i in 0...size
                val *= det[i, i]
            end
        end
        return val.to_i unless f
        return val
    end
#----------------------------------------------------------------
# # inspect
#----------------------------------------------------------------
#     返回表达行列式的字符串。
#----------------------------------------------------------------
    def inspect
        str = ""
        for i in rows
            str += i.inspect + "\n"
        end
        return str
    end
#----------------------------------------------------------------
# # to_s
#----------------------------------------------------------------
#     同inspect。
#----------------------------------------------------------------
    def to_s
        return inspect
    end
#----------------------------------------------------------------
# # to_a
#----------------------------------------------------------------
#     同rows。
#----------------------------------------------------------------
    def to_a
        return rows
    end
#----------------------------------------------------------------
# # to_f
#----------------------------------------------------------------
#     同value.to_f。
#----------------------------------------------------------------
    def to_f
        return value.to_f
    end
#----------------------------------------------------------------
# # to_i
#----------------------------------------------------------------
#     同value.to_i。
#----------------------------------------------------------------
    def to_i
        return value.to_i
    end
#----------------------------------------------------------------
# # self <=> other
#----------------------------------------------------------------
#     对self和other进行比较。若self.value较大时返回正数,若相等时返回0,
# 若较小时返回负数。
#----------------------------------------------------------------
    def <=>(other)
        if other.is_a?(Determinant)
            return value <=> other.value
        else
            return value <=> other
        end
    end
#----------------------------------------------------------------
# # eql?(other)
#----------------------------------------------------------------
#     若rows与other的rows用eql?比较为true则返回true,否则返回false。
#----------------------------------------------------------------
    def eql?(other)
        if other.is_a?(Determinant)
            return rows.eql?(other.rows)
        else
            return false
        end
    end
#----------------------------------------------------------------
# ## 属性
#----------------------------------------------------------------
#----------------------------------------------------------------
# # rows
#----------------------------------------------------------------
#     返回与行列式的内容一样的嵌套数组。
#     请参考Determinant.new
#----------------------------------------------------------------
    attr_accessor(:rows)
#----------------------------------------------------------------
# ## 私有方法
#----------------------------------------------------------------
#----------------------------------------------------------------
# # initialiaze(rows)
#----------------------------------------------------------------
#     行列式对象被建立之后初始化的方法,该方法的参数会全部传递给Determinant
# .new。这里定义了rows属性的初始值。
#----------------------------------------------------------------
    def initialize(rows)
        raise(TypeError) unless rows.is_a?(Array)
        for i in rows
            raise(TypeError) if !i.is_a?(Array) or i.size != rows.size
        end
        @rows = rows
    end
#----------------------------------------------------------------
# # initialiaze_copy(det)
#----------------------------------------------------------------
#     行列式对象被复制之后初始化的方法。
#     行列式的克隆中,它的rows和rows内部的数组都是原行列式对象的rows和rows
# 内部的数组的克隆。其余信息的克隆都和一般的对象相同,即Object类内的定义。
#----------------------------------------------------------------
    def initialize_copy(det)
        det.rows = rows.dup
        for i in 0...size
            det.rows = rows.dup
        end
    end
end[/pre][/fold]

点评

其实直接套定义,时间复杂度挺高的,用高斯消元会快一阶  发表于 2016-8-27 19:47
小仙女一枚~
梦石
0
星屑
9557
在线时间
5074 小时
注册时间
2013-6-21
回帖
3459

开拓者贵宾剧作品鉴家

发表于 2016-8-27 20:13:10 | 显示全部楼层
本帖最后由 RyanBern 于 2016-8-27 20:14 编辑

请自行 Google 计算机解线性方程组的正确姿势。

Cramer 法则在计算机中是个废的定理,没人会去用。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册会员

本版积分规则

Powered by Discuz! X5.0 © 2001-2026 Discuz! Team.

在本版发帖返回顶部