Can any one suggest me how to read EBCDIC Files (which generally comes form mainframe systems) using C.
EBCDIC:Extended Binary Coded Decimal Interchangable Code (not sure about the full form)
Can any one suggest me how to read EBCDIC Files (which generally comes form mainframe systems) using C.
EBCDIC:Extended Binary Coded Decimal Interchangable Code (not sure about the full form)
Read them the same way you read ASCII files, but you need to convert each character to the right character set once you read it or any output will be jumbled. There are conversion charts all over the web, and the process is simple. Here is one of those charts.
table lookup?
unsigned char Xlat[ 256 ];
unsigned char in, out;
out = xlat[ in ];
make sure input is unsigned as it is 8-bit, and a negative number will reference outside the array!
table lookup?
unsigned char Xlat[ 256 ];
unsigned char in, out;
out = xlat[ in ];
make sure input is unsigned as it is 8-bit, and a negative number will reference outside the array!
i got the chart thanks for that.But do i need to read each bytes then decode it according to the chart?
i got your concept but didn't get this code.
i got the chart thanks for that.But do i need to read each bytes then decode it according to the chart?
Yes.
Hey HI all,
Sory for reverting late onto this topic again.
Lets look into the chart:
e.g
ASCII EBCDIC HEX DEC BINARY
A * 41 65 0100 0001
We have an ebcdic file and have onechar *(assumeed) .
Now we will convert that to ASCII value.
but how to do it?
as HEX value is 41 for both.
2) Second question is how to print an EBCDIC char on screen?
3)Can any one qive small example of convertion of a single char A to its corresponding EBCDIC and print that on screen and again the reverse process.
Thanks,
DP
Hey HI all,
Sory for reverting late onto this topic again.Lets look into the chart:
e.gASCII EBCDIC HEX DEC BINARY A * 41 65 0100 0001
We have an ebcdic file and have onechar *(assumeed) .
Now we will convert that to ASCII value.
but how to do it?as HEX value is 41 for both.
2) Second question is how to print an EBCDIC char on screen?
3)Can any one qive small example of convertion of a single char A to its corresponding EBCDIC and print that on screen and again the reverse process.
Thanks,
DP
For the character 'A', it's 0x41 in ASCII and 0xC1 in EBCDIC. See this link:
http://www.flounder.com/ebcdictoascii1.htm
Printing EBCDIC characters to the screen would require the changing of codepages and the procedure is platform specific. Some OSes handle multipe codepages better than others.
Assuming you're on Windows, one "hack" way of doing this is:
1) Start a DOS command shell (or DOS box).
2) Run the command chcp 37 (this changes the codepage to 37 for this DOS session).
3) Change the font properties for this DOS session and choose the Lucinda Console font.
4) Write a simple program that merely prints out "ABC" in EBCDIC.
char ebcdicString[] = {0xC1, 0xC2, 0xC3, 0x00};
printf("%s\n", ebcdicString);
5) Run this program in the DOS shell where you issued the chcp command and you should see the characters ABC as output.
I suppose you could make a system call to change the code page from within your program - not a great solution but it does work.
If you ever want to view/edit files in other codepages, there is an excellent editor called EditPad Pro that has multi-codepage support including EBCDIC (or IBM037).
Hey i am successful in ASCII to ebcdic convertion.I felt that i should share my ideas.
Please find my approach:
step:1
--------
TO store ascii char list in a file.
#include<stdio.h>
int main()
{
int i;
FILE *fp1;
fp1=fopen("asclist","w");
if(fp1==NULL)return;
for(i=0;i<256;i++)
{
fprintf(fp1,"%c",i);
}
fclose(fp1);
return 0;
}
2)converted the ascii file to ebcdic using dd utility.
e.g
dd conv=ebcdic if=asclist of=ebclist
3)
step:3
-------
got the corresponding values form the file like this.
#include<stdio.h>
int main()
{
int i;
FILE *fp1;
fp1=fopen("ebclist","r");
if(fp1==NULL)return;
char ch;
ch=fgetc(fp1);
while(ch!=EOF)
{
fprintf(stdout,"%d\n",ch);
ch=fgetc(fp1);
}
printf("\n");
fclose(fp1);
return 0;
}
4)preapared asc and ebcdic chart.
5)Here are my convertion programs for ASCII TO EBCDIC CONVERTION
A slight change in the code can do EBCDIC to ASCII convertion also.
#include<stdio.h>
/*****************ASCII AND EBCDIC MAPPING CHART************************/
char ebcdic_chart[256]={0,1,2,3,55,45,46,47,22,5,37,11,12,13,14,15,16,
17,18,19,60,61,50,38,24,25,63,39,28,29,30,31,64,90,127,123,91,108,
80,125,77,93,92,78,107,96,75,97,-16,-15,-14,-13,-12,-11,-10,-9,-8,
-7,122,94,76,126,110,111,124,-63,-62,-61,-60,-59,-58,-57,-56,-55,-47,
-46,-45,-44,-43,-42,-41,-40,-39,-30,-29,-28,-27,-26,-25,-24,-23,-83,
-32,-67,-102,109,121,-127,-126,-125,-124,-123,-122,-121,-120,-119,
-111,-110,-109,-108,-107,-106,-105,-104,-103,-94,-93,-92,-91,-90,-89,
-88,-87,-64,79,-48,95,7,32,33,34,35,36,21,6,23,40,41,42,43,44,9,10,27,
48,49,26,51,52,53,54,8,56,57,58,59,4,20,62,-31,65,66,67,68,69,70,71,72,
73,81,82,83,84,85,86,87,88,89,98,99,100,101,102,103,104,105,112,113,114,
115,116,117,118,119,120,-128,-118,-117,-116,-115,-114,-113,-112,106,-101,
-100,-99,-98,-97,-96,-86,-85,-84,74,-82,-81,-80,-79,-78,-77,-76,-75,-74,
-73,-72,-71,-70,-69,-68,-95,-66,-65,-54,-53,-52,-51,-50,-49,-38,-37,-36,
-35,-34,-33,-22,-21,-20,-19,-18,-17,-6,-5,-4,-3,-2,255};
char ascii_chart[256]={0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,
17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,
38,39,40,41,42,43,44,45,46,47,48,49,50,51,52,53,54,55,56,57,58,
59,60,61,62,63,64,65,66,67,68,69,70,71,72,73,74,75,76,77,78,79,
80,81,82,83,84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,
101,102,103,104,105,106,107,108,109,110,111,112,113,114,115,116,
117,118,119,120,121,122,123,124,125,126,127,128,129,130,131,132,
133,134,135,136,137,138,139,140,141,142,143,144,145,146,147,148,
149,150,151,152,153,154,155,156,157,158,159,160,161,162,163,164,
165,166,167,168,169,170,171,172,173,174,175,176,177,178,179,180,
181,182,183,184,185,186,187,188,189,190,191,192,193,194,195,196,
197,198,199,200,201,202,203,204,205,206,207,208,209,210,211,212,
213,214,215,216,217,218,219,220,221,222,223,224,225,226,227,228,
229,230,231,232,233,234,235,236,237,238,239,240,241,242,243,244,
245,246,247,248,249,250,251,252,253,254,255};
/*****************END ASCII AND EBCDIC MAPPING CHART************************/
int asc_index(const char ch,char *list);
int main(int argc,char **argv)
{
if(argc!=3)
{
printf("improper Usage\n");
return;
}
FILE *fp1,*fp2;
fp1=fopen(argv[1],"rb");
if(fp1==NULL)return;
fp2=fopen(argv[2],"w");
if(fp2==NULL)return;
char ch,ch1;
ch=fgetc(fp1);
while(ch!=EOF)
{
int index;
index=asc_index(ch,ascii_chart);
if(index==-1)index=0;
fprintf(fp2,"%c",ebcdic_chart[index]);
fprintf(stdout,"%c",ascii_chart[index]);
ch=fgetc(fp1);
}
fclose(fp1);
fclose(fp2);
return 0;
}
int asc_index(char ch,char *list)
{
int i=0;
while(i<256)
{
if(ch==*(list+i))
return i;
i++;
}
return -1;
}
As i am successful in EBCDIC to ASCII convertion byte wise now i should proceed to next step.
We generally get EBCDIC files from mainframe system with COBOL copy book.In which TYpe of each columns are specified.
e.g
value with spaces( char )
PIC X
PIC S9
COMP.
COMP1
COMP2
COMP3
i am able to convert plane byte but not able to convert
packed decimal fields/comp bytes.
Can any one suggest how to proceed further.
I am attaching a COBOL COPY BOOK for reference..
**************************************************************
*** (C)COPYRIGHT FIRST DATA RESOURCES, INC. *
*** 1971 - 2008 *
*** ALL RIGHTS RESERVED. *
*** THIS MEDIA CONTAINS UNPUBLISHED, CONFIDENTIAL AND *
*** PROPRIETARY INFORMATION OF FIRST DATA RESOURCES, INC. *
*** NO DISCLOSURE OR USE OF ANY PORTION OF THE CONTENTS *
*** OF THESE MATERIALS MAY BE MADE WITHOUT THE EXPRESS *
*** WRITTEN CONSENT OF FIRST DATA RESOURCES, INC *
**************************************************************
*FDCSTAMP PGM (SSCHIPWS) REL (08) VER (193) RELDATE (07/11/08) *
**************************************************************
** FOR USE WITH FILE DEFINITION COPYBOOK SSCHIPFD **
** THIS COPYBOOK WILL BE THE WORKING STORAGE FOR THE **
** CHIPLOG FILE WITH SYS/PRIN/AGENT. **
**************************************************************
*** C O P Y B O O K C H A N G E S ***
*** SSCHIPWS ***
*** ***
*** 08193A 07/11/08 W7L0021 MOHR/T TM089 ***
*** VISA CONTACTLESS ***
*** 07194A 07/13/07 I6D0007C MOHR/T TM089 ***
*** EMV PHASE III ***
*** 01.000 04/13/07 I6D0007B MOHR/T TM089 ***
*** EMV PHASE II ***
**************************************************************
01 XXX-CHIPLOG-FMT-REC.
05 XXX-TRAN-CD PIC X(02) VALUE SPACES.
05 XXX-SYS-NR PIC X(04) VALUE SPACES.
05 XXX-PRIN-NR PIC X(04) VALUE SPACES.
05 XXX-AGENT-NR PIC X(04) VALUE SPACES.
05 XXX-CARD-ACCT-NR PIC X(19) VALUE SPACES.
05 XXX-PAN-SEQ-NR PIC X(03) VALUE SPACES.
05 XXX-MERCH-NR PIC X(16) VALUE SPACES.
05 XXX-TRAN-AMT PIC S9(11)V99 COMP-3
VALUE +0.
05 XXX-AUTH-CD PIC X(06) VALUE SPACES.
05 XXX-AUTH-XFER-CD PIC X(01) VALUE SPACES.
05 XXX-DECL-RESN-CD PIC X(04) VALUE SPACES.
05 XXX-ADDL-RESN-CD PIC X(02) VALUE SPACES.
05 XXX-MRCH-CAT-CD PIC X(04) VALUE SPACES.
05 XXX-MRCH-CRCY-CD PIC X(03) VALUE SPACES.
05 XXX-LOG-CPU-ID PIC X(01) VALUE SPACES.
05 XXX-CRHLDR-FILE PIC X(01) VALUE SPACES.
05 XXX-DATE-STAMP PIC S9(7)V COMP-3 VALUE +0.
05 XXX-TIME-STAMP PIC S9(7)V COMP-3 VALUE +0.
05 XXX-AUTH-ID PIC X(04) VALUE SPACES.
05 XXX-SORC-TERM-ID PIC X(04) VALUE SPACES.
05 XXX-OP-CD PIC X(03) VALUE SPACES.
05 XXX-EXP-DT PIC X(04) VALUE SPACES.
05 XXX-POS-ENTRY-MODE PIC X(02) VALUE SPACES.
05 XXX-PIN-VERIFY-TRAN PIC X(01) VALUE SPACES.
05 XXX-MRCH-POS-CAP PIC X(10) VALUE SPACES.
05 XXX-AUTH-PROC-FILE PIC X(01) VALUE SPACES.
05 XXX-TRAN-ID-SOURCE PIC S9(3) COMP-3 VALUE +0.
05 XXX-FDR-TRAN-ID.
10 XXX-BANKNET-REFNO PIC X(9) VALUE SPACES.
10 FILLER REDEFINES XXX-BANKNET-REFNO.
15 XXX-INDUSTRY-TRAN-ID PIC S9(15) COMP-3.
15 FILLER PIC X.
05 XXX-DOWN-GRADE-TRAN PIC X(01) VALUE SPACES.
05 XXX-ARQC-VERIFY-TRAN PIC X(01) VALUE SPACES.
05 XXX-ARPC-GENERATED-IND PIC X(01) VALUE SPACES.
05 XXX-FALL-BACK-TRANS PIC X(01) VALUE SPACES.
05 XXX-CVV-VER-USED-FLAG PIC X(01) VALUE SPACES.
05 XXX-CVM-METHOD PIC X(06) VALUE SPACES.
05 XXX-CVR-FIELD-SETTINGS PIC X(12) VALUE SPACES.
05 XXX-TVR-FIELD-SETTINGS PIC X(10) VALUE SPACES.
05 XXX-TERM-CAPABILITY PIC X(06) VALUE SPACES.
08193A 05 XXX-NO-SCRIPTS-SENT PIC S9(03) COMP-3 VALUE +0.
07194A 05 XXX-SCRIPT-TABLE OCCURS 10 TIMES.
10 XXX-SCRIPT-ID PIC X(03) VALUE SPACES.
08193A 05 FILLER PIC X(97) VALUE SPACES.
Before moving on to packed fields conversions, I would look at revising the code in your previous post. I think you have over complicated matters a bit.
For your arrays, you should use the type of unsigned char - wildgoose has advised this as well in an earlier post. You can then get rid of those negative values in the elements of your array. Probably doesn't hurt to make these arrays static as well.
Also, if you're only interested in EBCDIC to ASCII conversions, I don't understand why you need two tables. If you want to be able to convert in either direction then try something like:
static unsigned char asc2ebc[256] = {
0, 1, 2, 3, 55, 45, 46, 47, 22, 5, 37, 11, 12, 13, 14, 15,
16, 17, 18, 19, 60, 61, 50, 38, 24, 25, 63, 39, 28, 29, 30, 31,
64, 79,127,123, 91,108, 80,125, 77, 93, 92, 78,107, 96, 75, 97,
240,241,242,243,244,245,246,247,248,249,122, 94, 76,126,110,111,
124,193,194,195,196,197,198,199,200,201,209,210,211,212,213,214,
215,216,217,226,227,228,229,230,231,232,233, 74,224, 90, 95,109,
121,129,130,131,132,133,134,135,136,137,145,146,147,148,149,150,
151,152,153,162,163,164,165,166,167,168,169,192,106,208,161, 7,
32, 33, 34, 35, 36, 21, 6, 23, 40, 41, 42, 43, 44, 9, 10, 27,
48, 49, 26, 51, 52, 53, 54, 8, 56, 57, 58, 59, 4, 20, 62,225,
65, 66, 67, 68, 69, 70, 71, 72, 73, 81, 82, 83, 84, 85, 86, 87,
88, 89, 98, 99,100,101,102,103,104,105,112,113,114,115,116,117,
118,119,120,128,138,139,140,141,142,143,144,154,155,156,157,158,
159,160,170,171,172,173,174,175,176,177,178,179,180,181,182,183,
184,185,186,187,188,189,190,191,202,203,204,205,206,207,218,219,
220,221,222,223,234,235,236,237,238,239,250,251,252,253,254,255
};
static unsigned char ebc2asc[256] = {
0, 1, 2, 3,156, 9,134,127,151,141,142, 11, 12, 13, 14, 15,
16, 17, 18, 19,157,133, 8,135, 24, 25,146,143, 28, 29, 30, 31,
128,129,130,131,132, 10, 23, 27,136,137,138,139,140, 5, 6, 7,
144,145, 22,147,148,149,150, 4,152,153,154,155, 20, 21,158, 26,
32,160,161,162,163,164,165,166,167,168, 91, 46, 60, 40, 43, 33,
38,169,170,171,172,173,174,175,176,177, 93, 36, 42, 41, 59, 94,
45, 47,178,179,180,181,182,183,184,185,124, 44, 37, 95, 62, 63,
186,187,188,189,190,191,192,193,194, 96, 58, 35, 64, 39, 61, 34,
195, 97, 98, 99,100,101,102,103,104,105,196,197,198,199,200,201,
202,106,107,108,109,110,111,112,113,114,203,204,205,206,207,208,
209,126,115,116,117,118,119,120,121,122,210,211,212,213,214,215,
216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231,
123, 65, 66, 67, 68, 69, 70, 71, 72, 73,232,233,234,235,236,237,
125, 74, 75, 76, 77, 78, 79, 80, 81, 82,238,239,240,241,242,243,
92,159, 83, 84, 85, 86, 87, 88, 89, 90,244,245,246,247,248,249,
48, 49, 50, 51, 52, 53, 54, 55, 56, 57,250,251,252,253,254,255
};
char ascii_to_ebcdic(const unsigned char c) {
return asc2ebc[c];
}
char ebcdic_to_ascii(const unsigned char c) {
return ebc2asc[c];
}
Converting in either direction, you only need ONE mapping array per direction.
Cheers,
JD
Now as for packed fields, first of all do you understand the format for packed-decimal fields (comp-3)?
Packed decimal format means that each byte represents two decimal digits - so effectively each nibble (4 bits) represents a decimal digit. The low order nibble represents the sign of the number (hex 'F' for positive numbers and hex 'D' for negative).
An example will hopefully demonstrate the concept better than my explanation. Let's represent the number 98547 as packed decimal:
- in hex this is 0x98547F, and the binary representation would be:
1001 1000 | 0101 0100 | 0111 1111
The formula for how many bytes it takes to represent a number with n digits in packed decimal format is: n/2 + 1
Another example (with n being even), let's represent -6391 in packed decimal format - in hex it's 0x06391D
0000 0101 | 0011 1001 | 0001 1101
For your conversion routine you would have to make sure that your "nibbles" only represent decimal digits in the range 0-9 and the low order nibble is either 'F' or 'D'.
Rather than giving you a code example, see if you understand what I have said about packed decimal and have a go at writing the conversion.
Cheers,
JD
i tried they way u describe above.But are some problems:
examples:
-----------
dat_tran_dt packed decimal(10)
Actual the value is:20090809(i get it using a tool)
Value by my program:2|0x|ffffff90|ffffff80|5c
most of the fileds i get approx value but see the above example.
Another thing..:
Before moving on to packed fields conversions, I would look at revising the code in your previous post. I think you have over complicated matters a bit.
For your arrays, you should use the type of unsigned char - wildgoose has advised this as well in an earlier post. You can then get rid of those negative values in the elements of your array. Probably doesn't hurt to make these arrays static as well.
Also, if you're only interested in EBCDIC to ASCII conversions, I don't understand why you need two tables. If you want to be able to convert in either direction then try something like:
static unsigned char asc2ebc[256] = { 0, 1, 2, 3, 55, 45, 46, 47, 22, 5, 37, 11, 12, 13, 14, 15, 16, 17, 18, 19, 60, 61, 50, 38, 24, 25, 63, 39, 28, 29, 30, 31, 64, 79,127,123, 91,108, 80,125, 77, 93, 92, 78,107, 96, 75, 97, 240,241,242,243,244,245,246,247,248,249,122, 94, 76,126,110,111, 124,193,194,195,196,197,198,199,200,201,209,210,211,212,213,214, 215,216,217,226,227,228,229,230,231,232,233, 74,224, 90, 95,109, 121,129,130,131,132,133,134,135,136,137,145,146,147,148,149,150, 151,152,153,162,163,164,165,166,167,168,169,192,106,208,161, 7, 32, 33, 34, 35, 36, 21, 6, 23, 40, 41, 42, 43, 44, 9, 10, 27, 48, 49, 26, 51, 52, 53, 54, 8, 56, 57, 58, 59, 4, 20, 62,225, 65, 66, 67, 68, 69, 70, 71, 72, 73, 81, 82, 83, 84, 85, 86, 87, 88, 89, 98, 99,100,101,102,103,104,105,112,113,114,115,116,117, 118,119,120,128,138,139,140,141,142,143,144,154,155,156,157,158, 159,160,170,171,172,173,174,175,176,177,178,179,180,181,182,183, 184,185,186,187,188,189,190,191,202,203,204,205,206,207,218,219, 220,221,222,223,234,235,236,237,238,239,250,251,252,253,254,255 }; static unsigned char ebc2asc[256] = { 0, 1, 2, 3,156, 9,134,127,151,141,142, 11, 12, 13, 14, 15, 16, 17, 18, 19,157,133, 8,135, 24, 25,146,143, 28, 29, 30, 31, 128,129,130,131,132, 10, 23, 27,136,137,138,139,140, 5, 6, 7, 144,145, 22,147,148,149,150, 4,152,153,154,155, 20, 21,158, 26, 32,160,161,162,163,164,165,166,167,168, 91, 46, 60, 40, 43, 33, 38,169,170,171,172,173,174,175,176,177, 93, 36, 42, 41, 59, 94, 45, 47,178,179,180,181,182,183,184,185,124, 44, 37, 95, 62, 63, 186,187,188,189,190,191,192,193,194, 96, 58, 35, 64, 39, 61, 34, 195, 97, 98, 99,100,101,102,103,104,105,196,197,198,199,200,201, 202,106,107,108,109,110,111,112,113,114,203,204,205,206,207,208, 209,126,115,116,117,118,119,120,121,122,210,211,212,213,214,215, 216,217,218,219,220,221,222,223,224,225,226,227,228,229,230,231, 123, 65, 66, 67, 68, 69, 70, 71, 72, 73,232,233,234,235,236,237, 125, 74, 75, 76, 77, 78, 79, 80, 81, 82,238,239,240,241,242,243, 92,159, 83, 84, 85, 86, 87, 88, 89, 90,244,245,246,247,248,249, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57,250,251,252,253,254,255 }; char ascii_to_ebcdic(const unsigned char c) { return asc2ebc[c]; } char ebcdic_to_ascii(const unsigned char c) { return ebc2asc[c]; }
Converting in either direction, you only need ONE mapping array per direction.
Cheers,
JD
Is there any issue if i use signed char?
Anyways this approach is faster then my approach because here we dont need to search anything.
Its really good.
if u like the give some ideas about all the comp fileds
comp1
comp3
comp4 and
comp2
and its convertion....!!!
if u like the give some ideas about all the comp fileds
comp1
comp3
comp4 and
comp2and its convertion....!!!
If you google for these definitions, you'll find a truck load of information on their formats. In some way, the formats would be similar to the format I wrote about in my previous post - with some variations which are usually platform specific.
OK, it's Friday night here (oops early Saturday morning) and I'm feeling generous - so here's an example of "unpacking" a packed decimal field. Please bear in mind that there is no validation code for valid 0-9 values or the sign nibble (refer to my previous post) - I'll leave that up to you to code.
#include <stdio.h>
int unpack_comp3(long double *unpacked, const char packed[], size_t digits, size_t decprec);
int main(void) {
long double unpacked = 0;
unsigned char pd[] = { 0x08, 0x99, 0x66, 0x00, 0x71, 0x1F };
unpack_comp3(&unpacked, pd, 11, 3);
printf("The unpacked number is %.3Lf\n", unpacked);
return 0;
}
int unpack_comp3(long double *unpacked, const char packed[], size_t digits, size_t decprec) {
int i = 0;
int bytes;
int digit;
bytes = (digits / 2) + 1;
for (i = 0; i < bytes; ++i) {
// process the high order nibble
digit = packed[i] >> 4;
digit &= 0x0F;
*unpacked = (*unpacked * 10) + digit;
// process the low order nibble
digit = packed[i] & 0x0F;
// if we're processing the last byte - check the sign nibble
if (i == (bytes - 1)) {
if (digit == 0x0D) {
*unpacked *= -1;
}
} else {
*unpacked = (*unpacked * 10) + digit;
}
}
// adjust for required decimal precision
if (decprec > 0) {
for (i = 0; i < decprec; ++i) {
*unpacked /= 10;
}
}
// a different value should be returned (perhaps -1) if the input field is not a
// truly packed decimal field
return 0;
}
This code is a bit "quick" and could definitely be improved (perhaps by using the memxxx functions), but it does demonstrate an approach to solving this matter.
A note on the function interface - the first parameter is the returned unpacked value, the second parameter is the "packed string", the third parameter is the number of digits represented by the packed string (including decimal fractions) and the fourth parameter is the decimal precision (number of decimal places).
Try it out and see how you go.
Cheers,
JD
We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.