这里有人知道如何将 VB Double 转换为 Cobol S9(15)V99 Comp-3 数据类型吗?
1 回答
如果不需要在同一个程序中完成,在我看来,找到一个 VB和COBOL 都能理解的通用格式会更容易。
那将是文本。换句话说,最简单的解决方案可能是将数字作为文本“3.14159”写入文件,并让 COBOL 代码以该格式读取它并将MOVE
其写入COMP-3
字段?
如果这不可能,那COMP-3
是一个相当简单的 BCD 类型。无论如何,我会将数字转换为字符串,然后一次将两个字符转换为字节数组。
S9(15)V99 需要 18 个 nybble(一个 nybble 是 4 位,或半个八位字节)来存储:
- 整数位(十五个 nybbles)。
- 小数位(两个 nybbles)。
- 标志(一个nybble)。
小数点不需要空格,因为 aV
是隐含的小数,而不是真实的小数。
所以数字3.14
将表示为字节:
00 00 00 00 00 00 00 31 4C
唯一棘手的一点是最后的符号 nybble (C
用于正面和D
负面)。
这是我在 Excel VBA 中编写的一些代码(不幸的是,我没有在这台机器上安装 VB),它向您展示了如何做到这一点。makeComp3() 函数应该可以很容易地转移到一个真正的 VB 程序中。
宏测试程序输出值0
,49
和分别76
是 hex00
和31
( is )。4C
00314C
+3.14
第一步(在所有声明之后)是将双精度数乘以十的相关幂,然后将其转换为整数,从而使双精度数成为隐含的小数:
Option Explicit
' makeComp3. '
' inp is the double to convert. '
' sz is the minimum final size (with sign). '
' frac is the number of fractional places. '
Function makeComp3(inp As Double, sz As Integer, frac As Integer) As String
Dim inpshifted As Double
Dim outstr As String
Dim outbcd As String
Dim i As Integer
Dim outval As Integer
Dim zero As Integer
zero = Asc("0")
' Make implied decimal. '
inpshifted = Abs(inp)
While frac > 0
inpshifted = inpshifted * 10
frac = frac - 1
Wend
inpshifted = Int(inpshifted)
接下来,我们将其制成正确大小的字符串,以便于处理:
' Get as string and expand to correct size. '
outstr = CStr(inpshifted)
While Len(outstr) < sz - 1
outstr = "0" & outstr
Wend
If Len(outstr) Mod 2 = 0 Then
outstr = "0" & outstr
End If
然后我们一次处理该字符串两个数字,并将每一对组合成一个输出 nybble。最后一步是处理最后一个数字和符号:
' Process each nybble pair bar the last. '
outbcd = ""
For i = 1 To Len(outstr) - 2 Step 2
outval = (Asc(Mid(outstr, i)) - zero) * 16
outval = outval + Asc(Mid(outstr, i + 1)) - zero
outbcd = outbcd & Chr(outval)
Next i
' Process final nybble including the sign. '
outval = (Asc(Right(outstr, 1)) - zero) * 16 + 12
If inp < 0 Then
outval = outval + 1
End If
makeComp3 = outbcd & Chr(outval)
End Function
这只是测试工具,尽管它可能与更多测试用例有关:-)
Sub Macro1()
Dim i As Integer
Dim cobol As String
cobol = makeComp3(3.14159, 6, 2)
For i = 1 To Len(cobol)
MsgBox CStr(Asc(Mid(cobol, i)))
Next i
End Sub