how to format a number to S9(5)V99 ascii in .net

坚强是说给别人听的谎言 提交于 2019-12-05 10:51:36

What you have shown us here is the PICTURE clause portion of a COBOL data declaration.

COBOL data declarations are a bit odd and take some getting used to. Here is a link to an introductory tutorial on COBOL data declarations. This should get you started.

The PICture clause you have given in your question is defining a numeric item with the following characteristics:

  • S - Leading sign
  • 9(5) - 5 decimal digits
  • V - Implied decimal point
  • 99 - 2 digits after the implied decimal point

Basically, you are telling the COBOL compiler to define a numeric variable capable of holding the values -99999.99 through +99999.99. Exactly how the compiler will fulfill this request depends on the specific USAGE clause. However, for numeric items containing a fixed decimal position, the 'normal' USAGE is PACKED-DECIMAL or COMP-3 (these are just different names meaning the same thing). This link provides some introductory information concerning the storage representation of packed decimal data.

Packed decimal data are useful for doing numeric computations where the number of decimal points must remain fixed.

Writing packed decimal data to a report or terminal does not work particularly well. You must first convert it to a DISPLAYable format. This involves MOVEing the packed decimal value to another variable with a USAGE DISPLAY attribute. Suppose your packed decimal variable was called PACKED-DECIMAL-NBR and was holding the value -2345.01. You could define a display variable to hold it as:

01    DISPLAY-NBR     PIC +++,++9.99.

then when it comes time to write/display the value contained in PACKED-DECIMAL-NBR you would do something like:

MOVE PACKED-DECIMAL-NBR TO DISPLAY-NBR
DISPLAY DISPLAY-NBR

The MOVE converts the packed-decimal number to a character representation which you can display in reports or on the terminal. The value -2,345.01 is displayed.

S in cobol is the definition of a signed numeric field (ie can be positive or negative). So for example S999 is a signed 3 digit numeric (binary). Problem is S is assumed, and in most cobol compilers, the way the sign is marked is by "overpunching" the last character with another character to signify plus or minus. This results, if you look at the field in an ascii browser, you will have a strange character. Ie. MINUS 500 would look something like this 50C or 50} depending on the underlying character and if it were a + or - that had overpunched.

PIC S9(5)v99 isn't a number format. It's a description of how the data are stored and what it means there. For instance, a number stored as "-0010000" means -100.00.

What exactly are you trying to accomplish? Are you trying to send a decimal -100.00 to a COBOL program?


PIC -99,999.00 is a number format. It specifies to use a leading minus sign if the number is negative, to use five digits before the decimal place, with a comma between the thousands, a decimal point, then exactly two digits after. A number stored in a PIC S9(5)V99 field might reasonably be moved to a PIC -99,999.00 field.

Public Function CobolToDec(ByVal str As String) As Double

' **********************************************************************
' * Purpose:    Converts Cobol numbers into dubble-values in MS format.
' * Author:     Mikael Bergstrom
' * Date:       2017-11-06
' * Input:      str = Cobolcoded value for amount S9(13)V99(Cobol)
' *             Signs are in last byte
' **********************************************************************

Dim strNeg As String
strNeg = "pqrstuvwxy"


' If letter in strNeg then convert to number and negative sign
' p = 0, q = 1, r = 2 osv...

' Two last digits are decimals.
' Ex 00000000001200y = -120,09
' Ex 000000000015000 = 150,00

' Contains negative sign?
If InStr(1, str, "-", vbTextCompare) Then
    dectal = CDbl(Trim(str))
    CobolToDec = dectal
Else
' ...if not sign -> convert last digit to represetative digit and make hole number negative.
    lastbyte = LCase(Right(str, 1))
    If Not IsNumeric(lastbyte) Then
        If InStr(1, strNeg, lastbyte, vbTextCompare) > 0 Then
            dectal = "-" & Left(str, 13) & "," & Mid(str, 14, 1) & CStr(InStr(strNeg, lastbyte) - 1)
        Else
            ' not valid negative sign in strNeg (pqrstuvwxy)
            ' Set 0 ast last sign as we don?t know and make negative number
            dectal = "-" & Left(str, 13) & "," & Mid(str, 14, 1) & "0"
        End If
    Else
        ' positive number, just separate the two decimals
        dectal = Left(str, 13) & "," & Right(str, 2)
    End If

    ' Convert into double datatype and return result
    CobolToDec = CDbl(FormatNumber(dectal, 2, , , vbFalse))
End If

End Function

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!