Focal Point
converting decimal value to binair value

This topic can be found at:
https://forums.informationbuilders.com/eve/forums/a/tpc/f/7971057331/m/8951017612

March 06, 2007, 11:10 AM
FrankDutch
converting decimal value to binair value
I have a value let's say 50 that I want to convert into a binair value 110010
In excel I have the formula dec2bin that won't go far enough (try 2000 p.e.)

any idea

This message has been edited. Last edited by: FrankDutch,




Frank

prod: WF 7.6.10 platform Windows,
databases: msSQL2000, msSQL2005, RMS, Oracle, Sybase,IE7
test: WF 7.6.10 on the same platform and databases,IE7

March 06, 2007, 12:18 PM
Alan B
Only for DM, this just for whole numbers:
  
-DEFAULTS &INPUT = 49;
-SET &R = &INPUT;
-SET &O = 0;
-SET &CNTR = 1;
-REPEAT :LOOP 999 TIMES
-SET &N = IMOD(&R,2,'I1');
-SET &R = INT(&R/2);
-SET &O = IF &CNTR EQ 1 THEN &N ELSE &N | &O ;
-IF &R LT 1 GOTO :OUTLOOP;
-SET &CNTR = &CNTR+1;
-:LOOP
-:OUTLOOP
-TYPE &O



Alan.
WF 7.705/8.007
March 06, 2007, 12:31 PM
mikipago
There is no specific User Written Subroutine to convert a decimal Number to
hex or binary.

Try this workaround :

-*=======
DEFINE FUNCTION DECBIN8 (DECNUM/I3)
-*=======
-* THIS WORKS WITH A DECIMAL NUMBER OF 255 OR LESS ONLY;
-*
-*------- BINARY DIGIT 8
-*
BIND8 /A1 = IF DECNUM GE 128 THEN '1' ELSE '0';

-*------- BINARY DIGIT 7
-*
BINDR7 /I3 = IF BIND8 EQ '1' THEN DECNUM - 128 ELSE DECNUM;
BIND7 /A1 = IF BINDR7 GE 64 THEN '1' ELSE '0';

-*------- BINARY DIGIT 6
-*
BINDR6 /I3 = IF BIND7 EQ '1' THEN BINDR7 - 64 ELSE BINDR7;
BIND6 /A1 = IF BINDR6 GE 32 THEN '1' ELSE '0';

-*------- BINARY DIGIT 5
-*
BINDR5 /I3 = IF BIND6 EQ '1' THEN BINDR6 - 32 ELSE BINDR6;
BIND5 /A1 = IF BINDR5 GE 16 THEN '1' ELSE '0';

-*------- BINARY DIGIT 4
-*
BINDR4 /I3 = IF BIND5 EQ '1' THEN BINDR5 - 16 ELSE BINDR5;
BIND4 /A1 = IF BINDR4 GE 8 THEN '1' ELSE '0';

-*------- BINARY DIGIT 3
-*
BINDR3 /I3 = IF BIND4 EQ '1' THEN BINDR4 - 8 ELSE BINDR4;
BIND3 /A1 = IF BINDR3 GE 4 THEN '1' ELSE '0';

-*------- BINARY DIGIT 2
-*
BINDR2 /I3 = IF BIND3 EQ '1' THEN BINDR3 - 4 ELSE BINDR3;
BIND2 /A1 = IF BINDR2 GE 2 THEN '1' ELSE '0';

-*------- BINARY DIGIT 1
-*
BINDR1 /I3 = IF BIND2 EQ '1' THEN BINDR2 - 2 ELSE BINDR2;
BIND1 /A1 = IF BINDR1 EQ 1 THEN '1' ELSE '0';

DECBIN8 /A8 = BIND8 || BIND7 || BIND6 || BIND5 ||
BIND4 || BIND3 || BIND2 || BIND1 ;
END

-*=======
DEFINE FILE CAR
-*=======
DECNUM /I3 WITH CAR = 50 ;
BINVAL /A8 = DECBIN8 (DECNUM);

END

-*=======
TABLEF FILE CAR
-*=======
PRINT DECNUM
BINVAL

IF RECORDLIMIT EQ 1
END
-RUN

This code currently converts a decimal of 255 or less i.e 8 binary digits.
If you adjust this code to 16 bit binary it will convert decimals of 65535
or less i.e (2*(2 to the power of x)) -1 where x is the number of binary digits.

The DEFINE FUNCTION code can be INCLUDED in the EDASPROF.PRF file too.


WF 8.1.05M/8.2.06,CentOs,Windows,Oracle ,Postgress
March 06, 2007, 01:15 PM
Francis Mariani
mikipago, very nice function.

Good to see you're still working in WebFOCUS.


Francis


Give me code, or give me retirement. In FOCUS since 1991

Production: WF 7.7.05M, Dev Studio, BID, MRE, WebSphere, DB2 / Test: WF 8.1.05M, App Studio, BI Portal, Report Caster, jQuery, HighCharts, Apache Tomcat, MS SQL Server
March 06, 2007, 01:45 PM
FrankDutch
thanks
This will help and in my case Alan's solution fits best.




Frank

prod: WF 7.6.10 platform Windows,
databases: msSQL2000, msSQL2005, RMS, Oracle, Sybase,IE7
test: WF 7.6.10 on the same platform and databases,IE7

March 06, 2007, 02:01 PM
FrankDutch
quote:
Originally posted by Alan B:
Only for DM, this just for whole numbers:
  
-DEFAULTS &INPUT = 49;
-SET &R = &INPUT;
-SET &O = 0;
-SET &CNTR = 1;
-REPEAT :LOOP 999 TIMES
-SET &N = IMOD(&R,2,'I1');
-SET &R = INT(&R/2);
-SET &O = IF &CNTR EQ 1 THEN &N ELSE &N | &O ;
-IF &R LT 1 GOTO :OUTLOOP;
-SET &CNTR = &CNTR+1;
-:LOOP
-:OUTLOOP
-TYPE &O


Alan

I know what you want and this will be my solution, but ther is a small failure in it as far as I can see.
I think on line 9 you test if the &CNTR EQ 1, I think that is wrong, in any case you should concatenate the &N value to the string it would be something like 100101...
I need also the counters when the value &N is 1 so I'm going to print them.

Thanks anyway.




Frank

prod: WF 7.6.10 platform Windows,
databases: msSQL2000, msSQL2005, RMS, Oracle, Sybase,IE7
test: WF 7.6.10 on the same platform and databases,IE7

March 06, 2007, 02:26 PM
Alan B
Frank

The test on &CNTR Eq 1 will be the last digit in the string, if you remove it you will have an extra zero on the end. You could remove that check if you set &O to ' ', but then the string will have a blank on the end, which may, or may not, be important.


Alan.
WF 7.705/8.007
March 06, 2007, 02:36 PM
Tony A
A good method mikipago, but how about using the IMOD function instead?
DEFINE FUNCTION DECTOBIN(DECNUM/I5)
  DECTOBIN/A16 = IF DECNUM GE 65536 OR DECNUM LT 0 THEN 'ERROR' ELSE '';
  BIN_NUM0/I1  = IMOD(DECNUM, 2, 'I1');
  DECNUM       = DECNUM / 2;
  BIN_NUM1/I1  = IMOD(DECNUM, 2, 'I1');
  DECNUM       = DECNUM / 2;
  BIN_NUM2/I1  = IMOD(DECNUM, 2, 'I1');
  DECNUM       = DECNUM / 2;
  BIN_NUM3/I1  = IMOD(DECNUM, 2, 'I1');
  DECNUM       = DECNUM / 2;
  BIN_NUM4/I1  = IMOD(DECNUM, 2, 'I1');
  DECNUM       = DECNUM / 2;
  BIN_NUM5/I1  = IMOD(DECNUM, 2, 'I1');
  DECNUM       = DECNUM / 2;
  BIN_NUM6/I1  = IMOD(DECNUM, 2, 'I1');
  DECNUM       = DECNUM / 2;
  BIN_NUM7/I1  = IMOD(DECNUM, 2, 'I1');
  DECNUM       = DECNUM / 2;
  BIN_NUM8/I1  = IMOD(DECNUM, 2, 'I1');
  DECNUM       = DECNUM / 2;
  BIN_NUM9/I1  = IMOD(DECNUM, 2, 'I1');
  DECNUM       = DECNUM / 2;
  BIN_NUMA/I1  = IMOD(DECNUM, 2, 'I1');
  DECNUM       = DECNUM / 2;
  BIN_NUMB/I1  = IMOD(DECNUM, 2, 'I1');
  DECNUM       = DECNUM / 2;
  BIN_NUMC/I1  = IMOD(DECNUM, 2, 'I1');
  DECNUM       = DECNUM / 2;
  BIN_NUMD/I1  = IMOD(DECNUM, 2, 'I1');
  DECNUM       = DECNUM / 2;
  BIN_NUME/I1  = IMOD(DECNUM, 2, 'I1');
  DECNUM       = DECNUM / 2;
  BIN_NUMF/I1  = IMOD(DECNUM, 2, 'I1');
  DECTOBIN/A16 = IF DECTOBIN EQ 'ERROR' THEN 'ERROR'
            ELSE EDIT(BIN_NUMF)||EDIT(BIN_NUME)||EDIT(BIN_NUMD)||EDIT(BIN_NUMC)
               ||EDIT(BIN_NUMB)||EDIT(BIN_NUMA)||EDIT(BIN_NUM9)||EDIT(BIN_NUM8)
               ||EDIT(BIN_NUM7)||EDIT(BIN_NUM6)||EDIT(BIN_NUM5)||EDIT(BIN_NUM4)
               ||EDIT(BIN_NUM3)||EDIT(BIN_NUM2)||EDIT(BIN_NUM1)||EDIT(BIN_NUM0);
END
-RUN

This copes with numbers upto 65535 and returns ERROR if this is exceeded.

Use this code to test
-SET &Cnt = 1;
-REPEAT :Loop 17 TIMES;
-SET &MyBin = DECTOBIN(&Cnt);
-TYPE &Cnt &MyBin
-SET &Cnt = &Cnt * 2;
-:Loop


T



In FOCUS
since 1986
WebFOCUS Server 8.2.01M, thru 8.2.07 on Windows Svr 2008 R2  
WebFOCUS App Studio 8.2.06 standalone on Windows 10 
March 06, 2007, 03:11 PM
Danny-SRL
Frank,
I understand that you want to translate a number in DM to a bit string. So here is my contribution.

-SET &N=50;
DEFINE FILE CAR
NB/I9 WITH COUNTRY=&N;
END
TABLE FILE CAR
PRINT NB
IF RECORDLIMIT EQ 1
ON TABLE SAVB
END
-RUN
-READ SAVB &A1.A1. &A2.A1. &A3.A1. &A4.A1.
-RUN
-SET &A=&A4 | &A3 | &A2 | &A1;
-SET &BITS='';
-REPEAT #BITS FOR &I FROM 1 TO 32;
-SET &BITS=&BITS || EDIT(BITSON(&I, &A, 'I1'), '9');
-#BITS
-SET &SIGBITS = TRIM('L', &BITS, 32, '0', 1, 'A32');
-TYPE BITS=&BITS
-TYPE SIGBITS=&SIGBITS

You should get the following:
BITS=00000000000000000000000000110010
SIGBITS=110010


Daniel
In Focus since 1982
wf 8.202M/Win10/IIS/SSA - WrapApp Front End for WF

March 06, 2007, 03:38 PM
FrankDutch
thanks Alan and all the others
I think Alan's is the best one in this case cause I need to go up to a 45 length bin number




Frank

prod: WF 7.6.10 platform Windows,
databases: msSQL2000, msSQL2005, RMS, Oracle, Sybase,IE7
test: WF 7.6.10 on the same platform and databases,IE7

March 06, 2007, 04:30 PM
Tony A
The only problem I can foresee is trying put a nine digit integer into the DM process from Alan, which you will have to do, Frank, if you need a 45 bit binary number. 99999999 will only give you 28 bits.

To get 45 bits your maximum number would be 35184372088831.

You might be able to utilise Danny's approach as you will not have the restriction on number of digits in the input, but you would have to move away from Integer input and use another numeric format.

T



In FOCUS
since 1986
WebFOCUS Server 8.2.01M, thru 8.2.07 on Windows Svr 2008 R2  
WebFOCUS App Studio 8.2.06 standalone on Windows 10 
March 06, 2007, 04:47 PM
FrankDutch
I know how to handle that
I will put the "number" an alpha string and split that in 2 times 23.
the 23 will work
and the second 23 will work too and the only thing I have to do at the end is add 23 to the results of the second calculated numbers (sounds a bit confusing, certainly when you do not know what I'm going to use this for, but it will work.)

When it is finished I will try to write the whole thing in a proper white paper.
It will be used for restricting or allowing users or usergroups to certain reports and projects.




Frank

prod: WF 7.6.10 platform Windows,
databases: msSQL2000, msSQL2005, RMS, Oracle, Sybase,IE7
test: WF 7.6.10 on the same platform and databases,IE7

March 07, 2007, 05:44 AM
Danny-SRL
Frank,

Here is my program modified for up to 48 bits.

-SET &N=1234567891234;
DEFINE FILE CAR
DB/D15c WITH COUNTRY=&N;
B24/I11 = 2**24;
NB0/I11 = IMOD(DB,B24,'I11');
NB1/I11 = INT(DB/B24);
DB2/D15c= NB1*B24 + NB0;
END
TABLE FILE CAR
PRINT NB0 NB1
IF RECORDLIMIT EQ 1
ON TABLE SAVB
END
-RUN
-READ SAVB &A1.A1. &A2.A1. &A3.A1. &B.A1. &A4.A1. &A5.A1. &A6.A1.
-RUN
-SET &A=&A6 | &A5 | &A4 | &A3 | &A2 | &A1;
-SET &BITS='';
-REPEAT #BITS FOR &I FROM 1 TO 48;
-SET &BITS=&BITS || EDIT(BITSON(&I, &A, 'I1'), '9');
-#BITS
-SET &SIGBITS = TRIM('L', &BITS, 48, '0', 1, 'A48');
-TYPE BITS=&BITS
-TYPE SIGBITS=&SIGBITS

For the input I have entered you get:
BITS=000000010001111101110001111110110000100100100010
SIGBITS=10001111101110001111110110000100100100010

I checked it with Windows' scientific calculator.

Good luck.


Daniel
In Focus since 1982
wf 8.202M/Win10/IIS/SSA - WrapApp Front End for WF

March 07, 2007, 07:35 AM
mikipago
Frank,

Here is a 64 bits version using the MOD function from Tony A.

-SET &MaxDec= 18446744073709551616 ;
-SET &MaxDig= 64 ;

-*=======
DEFINE FUNCTION DECTOBIN (DECNUM/D20)
-*=======
ERROR /I1 = DECNUM GE &MaxDec OR DECNUM LT 0 ;

-REPEAT :LOOP1 FOR &I FROM 1 TO &MaxDig STEP 1 ;
BIN_NUM&I/D1 = DMOD (DECNUM, 2 , 'D1');
DECNUM /D20 = DECNUM / 2 ;
-:LOOP1

DECTOBIN/A&MaxDig = IF ERROR THEN 'ERROR' ELSE
-REPEAT :LOOP2 FOR &J FROM &MaxDig TO 2 STEP -1 ;
EDIT (BIN_NUM&J) ||
-:LOOP2
EDIT (BIN_NUM1) ;
END
-RUN

-SET &Dec = 50;
-SET &Bin = DECTOBIN (&Dec);
-TYPE &Dec = (&Bin)

Result is :

50 = (0000000000000000000000000000000000000000000000000000000000110010)

P.S. Thanks Francis. It's good to be back. I'll try to contact you by email soon.
Michel


WF 8.1.05M/8.2.06,CentOs,Windows,Oracle ,Postgress
March 07, 2007, 08:56 AM
jgelona
You guys are killing me. Smiler

How long has DEFINE FUNCTION been available?


In FOCUS since 1985. Prod WF 8.0.08 (z90/Suse Linux) DB (Oracle 11g), Self Serv, Report Caster, WebServer Intel/Linux.
March 07, 2007, 09:55 AM
FrankDutch
Ok

thanks all for the support and remarks.
my program is now working as it should be.

I use this to test the fingerprint of a user against the fingerprint of the report.

In a small table I have all the used databases.
when I start a project I calculated a number based on the used databases for this special project.
A USER or a group of USERS is allowed to read from several databases or database tables.
That gives him also a number, composed the same way.

If someone tries to run a report that is part of a project the (incuded) proces checks if he is allowed to based on the above mentioned numbers.

If you want to I will send the masters and build proces. (Will take a while since I have to translate some fields into English)

Send me a privat message with your mail.

Frank




Frank

prod: WF 7.6.10 platform Windows,
databases: msSQL2000, msSQL2005, RMS, Oracle, Sybase,IE7
test: WF 7.6.10 on the same platform and databases,IE7

March 07, 2007, 10:05 AM
mikipago
Hi jgelona !

The DEFINE FUNCTION exist since version 5. It's very usefull sometimes.
By the way, I have in my pocket another nice function that convert a 32 byte
Hexadecimal value to a 32 byte decimal value.

Here is the code :

-*=======
DEFINE FUNCTION HEXTODEC (VALHEX/ A32 )
-*=======
VHEX /A32 = RJUST (32, VALHEX,'A32');

-SET &C = 1;
-REPEAT LOOP1 FOR &I FROM 32 TO 1 STEP -1 ;
CS&I /A1 = SUBSTR (32, VHEX, &C,&C,1 ,'A1');
-SET &C = &C + 1;
-LOOP1

-REPEAT LOOP2 FOR &J FROM 32 TO 1 STEP -1;
CD&J /A2 = DECODE CS&J ( '0' '00' '1' '01' '2' '02' '3' '03'
'4' '04' '5' '05' '6' '06' '7' '07'
'8' '08' '9' '09' 'A' '10' 'B' '11'
'C' '12' 'D' '13' 'E' '14' 'F' '15'
ELSE '00');
-LOOP2

VDEC /P32 =
-REPEAT LOOP3 FOR &K FROM 32 TO 3 STEP -2;
-SET &C = &K - 1;
-SET &E = &K - 2;
(EDIT (CD&K)) * (16**&C) +
(EDIT (CD&C)) * (16**&E) +
-LOOP3
(EDIT (CD2 )) * (16) +
(EDIT (CD1 )) ;

CV32 /I1 = VDEC / (10**31) ;
CN32 /P32 = VDEC - (CV32 * (10**31));
CA32 /A1 = IF CV32 EQ 0 THEN ' ' ELSE EDIT (CV32);
-REPEAT LOOP4 FOR &L FROM 32 TO 2 STEP -1;
-SET &C = &L - 1;
-SET &E = &L - 2;
CV&C /I1 = CN&L / (10**&E) ;
CN&C /P32 = CN&L - (CV&C * (10**&E));
CA&C /A1 = IF CA&L EQ ' ' AND
CV&C EQ 0 THEN ' ' ELSE EDIT (CV&C);
-LOOP4
CV1 /I1 = CN2 ;
CA1 /A1 = EDIT (CV1 ) ;

HALP /A32 =
-REPEAT LOOP5 FOR &M FROM 32 TO 2 STEP -1;
CA&M |
-LOOP5
CA1 ;

HALPL /A32 = LJUST ( 32, HALP ,'A32');
HEXTODEC/A32 = IF VALHEX EQ ' ' THEN ' ' ELSE HALPL ;

END
-RUN

-*ET &hex = 'FF ';
-*ET &hex = 'A8CD7891234BCDEFABCDEF9876AAA432';
-SET &hex = 'A8CD7891234 ';
-SET &dec = HEXTODEC (&hex);
-TYPE &hex = (&dec)

Result is :

A8CD7891234 = (11600027783732 )


WF 8.1.05M/8.2.06,CentOs,Windows,Oracle ,Postgress
March 07, 2007, 10:08 AM
Alan B
Michel

You have to be careful here, DMOD won't work on values over 9007199254740992, though other non-function based maths will work.

The maximum binary length you can get using DMOD is therefore 54 characters.

And just so it doesn't feel left out, the same thing in MAINTAIN (my favourite language):
  
-SET &IN='9007199254740992';
FILEDEF BINOUT DISK BINOUT.DAT (LRECL 54
-RUN
MAINTAIN
Declare In/P17 = ∈ Out/A0; Bin/d2;
If In gt 9007199254740992 begin
    type on binOut "Error in field value"; goto exit;
  endbegin
Repeat 56
Bin = dmod(In,2,Bin); In = int(In/2); Out = Bin | Out ;
if In lt 1 goto ExitRepeat;
EndRepeat
type on binOut "<Out";
END
-RUN
-READ BINOUT &longBinary.A54.
-TYPE BIN: &longBinary



Alan.
WF 7.705/8.007