纯代码实现浮点计算实际上对浮点算法的再实践。IEEE浮点表示法是Modbus RTU协议至今还在用的传送编码,更是WITS 1记录标准的基础。以往实现 MKI、CVI,MKL、CVL,MKS、CVS,MKD、CVD在高级语言里封装了现成的语句,现在PowerBasic和FreeBasic也可以将这些语句封闭到 DLL 中供其它语言调用。不过还是重编代码,对算法的演练更到位。
1. MKI/CVI
要点:对输入数据取整,判断正负,正数直接转换,负数加上65536后转换。输入数据分成高低各16位数据,范围在 &H0000 - &HFFFF之间。
Function MKI(ByVal iData As Integer) As String
'MKI 16bits &HFFFF -32768 to 32767 8000-7fff
Dim inData As Long
Dim HiByte As Long, LoByte As Long
inData = Fix(iData)
If inData < 0 Then inData = inData + 65536
LoByte = inData And &HFF
HiByte = (inData \ 2 ^ 8) And &HFF
MKI = Right$(("0" + Hex$(HiByte)), 2) + Right$(("0" + Hex$(LoByte)), 2)
End Function
2. MKL/CVl
MKL实现方法与MKI类似,它是32位的,因此输入的数据分成四个8位数据,在VB6中用Currency类型变量表示更便于计算。
Function MKL(ByVal lData As Long) As String
Dim Phi4 As Currency, Phi3 As Currency, Phi2 As Currency, Phi1 As Currency
Dim inData As Currency
inData = Fix(lData)
Phi4 = inData And &HFF
Phi3 = (inData \ 2 ^ 8) And &HFF
Phi2 = (inData \ 2 ^ 16) And &HFF
Phi1 = (inData \ 2 ^ 24) And &HFF
MKL = Right$(("0" + Hex$(Phi1)), 2) + Right$(("0" + Hex$(Phi2)), 2) + Right$(("0" + Hex$(Phi3)), 2) + Right$(("0" + Hex$(Phi4)), 2)
End Function
3. MKS/CVS
右移位求得整数部分二进制串,小数部分乘2取整形成小数二进制串,合并二进制串左移或右移小数点位置并舍去高位的 1 ,移位值加上127形成 exp 指数, 正负符号用0或1表示,结果是 s+exp+余下的小数。
OffSetBits = 8
AcuFactor = 32: OffSet = 127
inData = sData
inDataSingn = 0
If inData < 0 Then inDataSingn = 1
inData = Abs(inData) 'ignore singn
ipart = Int(inData): fpart = (inData - ipart)
If inData = 0 Then
CaseID = 0
Else
'Convert ipart, the integer part, into byte array TempData1 MSB to LSB
tipart = ipart: TempString = ""
For I = 1 To AcuFactor
TempString = Right$(Str$(tipart And &H1), 1) + TempString
tipart = tipart \ 2 ^ 1
Next I
For I = 1 To AcuFactor
If Mid$(TempString, I, 1) = "1" Then Exit For
Mid$(TempString, I, 1) = " "
Next I
IntiStr = Trim(TempString)
'Convert fpart, the fraction part, into byte array TempData2
tfpart = fpart: TempString = ""
For I = 1 To AcuFactor
If tfpart = 0 Then Exit For
tfpart = tfpart * 2
tnpart = Int(tfpart): tfpart = tfpart - tnpart
TempString = TempString + Right$(Str$(tnpart And &H1), 1)
Next I
FracStr = TempString
If ipart > 0 Then CaseID = 1
If ipart = 0 Then CaseID = 2
End If
4. MKD/CVD
与MKS类同,只是exp由8位增加至11位,偏移值由127变为1023
OffSetBits = 11
AcuFactor = 64: OffSet = 1023
inData = sData
inDataSingn = 0
If inData < 0 Then inDataSingn = 1
inData = Abs(inData) 'ignore singn
ipart = Int(inData): fpart = (inData - ipart)
If inData = 0 Then
CaseID = 0
Else
'Convert ipart, the integer part, into byte array TempData1 MSB to LSB
tipart = ipart: TempString = ""
For I = 1 To AcuFactor
TempString = Right$(Str$(tipart And &H1), 1) + TempString
tipart = tipart \ 2 ^ 1
Next I
For I = 1 To AcuFactor
If Mid$(TempString, I, 1) = "1" Then Exit For
Mid$(TempString, I, 1) = " "
Next I
IntiStr = Trim(TempString)
'Convert fpart, the fraction part, into byte array TempData2
tfpart = fpart: TempString = ""
For I = 1 To AcuFactor
If tfpart = 0 Then Exit For
tfpart = tfpart * 2
tnpart = Int(tfpart): tfpart = tfpart - tnpart
TempString = TempString + Right$(Str$(tnpart And &H1), 1)
Next I
FracStr = TempString
If ipart > 0 Then CaseID = 1
If ipart = 0 Then CaseID = 2
End If
最后的结果都要变成十六进制字符,以便传送和文件存储。
源代码下载:
https://download.csdn.net/download/weixin_45707491/88232263?spm=1001.2014.3001.5503