|
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件 ★ 免费下载 ★ ★ 使用帮助★
本帖最后由 weixing1531 于 2019-12-4 18:32 编辑
最近在学习类模块
手痒就试着编写了一个分数类
初学
不足之处请多多指教
以下为源代码:
类模块代码- '类模块 (名称) 改为 Rational
- 'Creat 构造方法
- 'RalAddRal RalAddNum 加法 函数
- 'RalSubRal RalSubNum 减法 函数
- 'RalTimesRal RalTimesNum 乘法 函数
- 'RalDivRal RalDivNum 除法 函数
- 'RalPowerInt 乘方 函数
- 'Negative 相反数 函数
- 'Real2Ral 浮点数转换为分数 子程序
- 'Ral2Real 分数转换为双精度浮点数 函数
- 'Output 打印 子程序
- Option Explicit
- Private num_& '分子 &代表长整数 4字节 下同
- Private denom_& '分母
- Private Sub Class_Initialize() '指定分数初始值
- num_ = 0
- denom_ = 1
- End Sub
- '个人认为写操作用子程序比用属性更安全
- Public Sub Setnum(x&) '写分子 子程序
- num_ = x
- End Sub
- Public Sub Setdenom(y&) '写分母 子程序
- denom_ = y
- End Sub
- '属性只可读
- Public Property Get num&() '读分子 属性
- num = num_
- End Property
- Public Property Get denom&() '读分母 属性
- denom = denom_
- End Property
- Public Sub Creat(x&, Optional y&) '构造方法
- num_ = x
-
- If IsMissing(y) Then '不传入分母
- denom_ = 1 '分母默认为1
- Else '传入分母
- If (y <= 0) Then
- MsgBox "分母不能为非正数!", vbExclamation
- End ' 提前结束程序
- End If
- denom_ = y
- End If
-
- 'Call Reduse(Me) '这里暂不进行约分
- End Sub
- Private Function Gcv&(a&, b&) '返回最大公约数
- Dim big&, small&, temp&
- big = Application.Max(a, b) 'VBA居然没有内置max min函数
- small = Application.Min(a, b)
- Do While (small > 1) '辗转除法
- temp = big Mod small
- If temp = 0 Then Exit Do
- big = small
- small = temp
- Loop
- Gcv = small
- End Function
-
- Private Sub Reduse(a As Rational) '约分 调用后改变了a
- Dim b&, sign&
- If a.denom = 0 Then
- MsgBox "分母不能为0!", vbExclamation
- End ' 提前结束程序
- End If
- If a.num = 0 Then '分子为0
- Call a.Setdenom(1) '分母强制为1
- Exit Sub '提前返回
- End If
- 'If a.num * a.denom > 0 Then '同号 积超大可能会溢出
- If (a.num > 0 And a.denom > 0) Or (a.num < 0 And a.denom < 0) Then '同号
- sign = 1
- Else '异号
- sign = -1
- End If
- Call a.Setnum(Abs(a.num)) '正分子
- Call a.Setdenom(Abs(a.denom)) '正分母
- b = Gcv(a.num, a.denom) '最大公约数
- Call a.Setnum(a.num / b * sign) '分子带符号
- Call a.Setdenom(a.denom / b) '保证分母始终为正
- End Sub
-
- Public Function RalAddRal(b As Rational) As Rational '加法
- Set RalAddRal = New Rational '对象实例
-
- Call RalAddRal.Setnum(num_ * b.denom + b.num * denom_)
- Call RalAddRal.Setdenom(denom_ * b.denom) '通分
- Call Reduse(RalAddRal) '约分
- End Function
- Public Function RalAddNum(b As Variant) As Rational '加法
- '利用VarType实现简单重载 b可以为整数、浮点数
- Select Case VarType(b) 'VarType返回变体的具体类型
- Case vbInteger, vbLong, vbByte 'Integer Long Byte整数
- Set RalAddNum = New Rational '对象实例
- Call RalAddNum.Setnum(num_ + denom_ * b)
- Call RalAddNum.Setdenom(denom_)
- Call Reduse(RalAddNum) '约分
- Case vbDouble, vbSingle '双、单精度浮点数
- Dim temp As New Rational
- Call temp.Real2Ral(CDbl(b)) 'CDbl将变体类型转换为双精度浮点数
- '转换为分数相加 单精度转换为分数可能误差较大
- Set RalAddNum = Me.RalAddRal(temp) 'Me为对象实例
- '加法已经约分过了
- Set temp = Nothing
- Case Else
- MsgBox "类型错误!", vbExclamation
- End ' 提前结束程序
- End Select
- End Function
- Public Function RalSubRal(b As Rational) As Rational '减法
- Set RalSubRal = New Rational '对象实例
-
- Call RalSubRal.Setnum(num_ * b.denom - b.num * denom_)
- Call RalSubRal.Setdenom(denom_ * b.denom) '通分
- Call Reduse(RalSubRal) '约分
- End Function
- Public Function RalSubNum(b As Variant) As Rational '减法
- 'a-b=a+(-b)
- Set RalSubNum = Me.RalAddNum(-b) 'Me为对象实例
- End Function
- Public Function RalTimesRal(b As Rational) As Rational '乘法
- Set RalTimesRal = New Rational '对象实例
-
- Call RalTimesRal.Setnum(num_ * b.num)
- Call RalTimesRal.Setdenom(denom_ * b.denom)
- Call Reduse(RalTimesRal) '约分
- End Function
- Public Function RalTimesNum(b As Variant) As Rational '乘法
- '利用VarType实现简单重载 b可以为整数、浮点数
- Select Case VarType(b) 'VarType返回变体的具体类型
- Case vbInteger, vbLong, vbByte 'Integer Long Byte整数
- Set RalTimesNum = New Rational '对象实例
- Call RalTimesNum.Setnum(num_ * b)
- Call RalTimesNum.Setdenom(denom_)
- Call Reduse(RalTimesNum) '约分
- Case vbDouble, vbSingle '双、单精度浮点数
- Dim temp As New Rational
- Call temp.Real2Ral(CDbl(b)) 'CDbl将变体类型转换为双精度浮点数
- '转换为分数相乘 单精度转换为分数可能误差较大
- Set RalTimesNum = Me.RalTimesRal(temp) 'Me为对象实例
- '乘法已经约分过了
- Set temp = Nothing
- Case Else
- MsgBox "类型错误!", vbExclamation
- End ' 提前结束程序
- End Select
- End Function
- Public Function RalDivRal(b As Rational) As Rational '除法
- Set RalDivRal = New Rational '对象实例
-
- Call RalDivRal.Setnum(num_ * b.denom)
- Call RalDivRal.Setdenom(denom_ * b.num)
- Call Reduse(RalDivRal) '约分
- End Function
- Public Function RalDivNum(b As Variant) As Rational '除法
- '利用VarType实现简单重载 b可以为整数、浮点数
- Select Case VarType(b) 'VarType返回变体的具体类型
- Case vbInteger, vbLong, vbByte 'Integer Long Byte整数
- Set RalDivNum = New Rational '对象实例
- Call RalDivNum.Setnum(num_)
- Call RalDivNum.Setdenom(denom_ * b)
- Call Reduse(RalDivNum) '约分
- Case vbDouble, vbSingle '双、单精度浮点数
- Dim temp As New Rational
- Call temp.Real2Ral(CDbl(b)) 'CDbl将变体类型转换为双精度浮点数
- '转换为分数相除 单精度转换为分数可能误差较大
- Set RalDivNum = Me.RalDivRal(temp) 'Me为对象实例
- '乘法已经约分过了
- Set temp = Nothing
- Case Else
- MsgBox "类型错误!", vbExclamation
- End ' 提前结束程序
- End Select
- End Function
- Public Function RalPowerInt(b&) As Rational '乘方
- Set RalPowerInt = New Rational '对象实例
-
- If b > 0 Then
- Call RalPowerInt.Setnum(num_ ^ b)
- Call RalPowerInt.Setdenom(denom_ ^ b)
- ElseIf b < 0 Then
- Call RalPowerInt.Setnum(denom_ ^ (-b))
- Call RalPowerInt.Setdenom(num_ ^ (-b))
- Else 'b==0 0^1=1
- Call RalPowerInt.Setnum(1)
- Call RalPowerInt.Setdenom(1)
- Exit Function '提前返回
- End If
-
- Call Reduse(RalPowerInt) '约分
- End Function
- '浮点数转换为分数
- '应该会有更好的算法 这里用的是暴力转换
- Public Sub Real2Ral(a As Double)
- Const N As Long = 100000
- Dim i As Long
-
- i = Fix(a) '取整 去尾
- denom_ = N '假定分母超大
- num_ = CLng((a - i) * N) '小数部分扩大N倍后四舍五入
- Call Reduse(Me) '约分后一定真分数
- num_ = num_ + i * denom_ '真分数叠加整数
- End Sub
- '分数转换为双精度浮点数
- Public Function Ral2Real() As Double
- If denom_ = 0 Then
- MsgBox "分母为0!", vbExclamation
- End ' 提前结束程序
- End If
-
- Ral2Real = num_ / denom_
- End Function
- Public Function Negative() As Rational '相反数 取负
- Set Negative = New Rational '对象实例
- Call Negative.Setdenom(denom_)
- Call Negative.Setnum(-num_)
- End Function
- Public Sub Output() '打印
- Debug.Print num_ & "/" & denom_ '立即窗口显示结果
- End Sub
复制代码
标准模块代码
- Option Explicit
- Sub main()
- Dim a As New Rational '对象实例
- Dim b As New Rational '对象实例
- Dim c As Rational 'c是引用 下同
- Call a.Creat(1, 2)
- Call a.Output
- Call b.Creat(1, 3)
- Call b.Output
- Set c = a.RalAddRal(b) '分数加分数
- Call c.Output '打印
- Set c = a.RalAddNum(2.25) '分数加数字
- Call c.Output '打印
- Set c = a.RalSubRal(b) '分数减分数
- Call c.Output
- Set c = a.RalSubNum(2.25) '分数减数字
- Call c.Output '打印
- Set c = a.RalTimesRal(b) '分数乘分数
- Call c.Output
- Set c = a.RalTimesNum(2.25) '分数乘数字
- Call c.Output '打印
- Set c = a.RalDivRal(b) '分数除以分数
- Call c.Output
- Set c = a.RalDivNum(2.25) '分数除以数字
- Call c.Output '打印
- Set c = a.RalPowerInt(3) '乘方
- Call c.Output
- Set c = a.Negative() '取相反数
- Call c.Output
- Call c.Real2Ral(-1.125) '浮点数转换为分数
- Call c.Output
- End Sub
复制代码
分数类型(试验).zip
(26.04 KB, 下载次数: 7)
|
|