‎2011 Sep 27 4:48 PM
Hello master.
I created a function that calculate a number from a string of numbers.
I checked and it works, but the string that needs to use the function is long
cadena = 0200000005500002133200000154700076945190
cadena that i need to work with is 40 lenght. I checked it with 30 lenght and it worked. how can i make it work with a lenght of 40???
FUNCTION zcalculo_dv.
*"----------------------------------------------------------------------
*"*"Interfase local
*" IMPORTING
*" REFERENCE(CADENA) TYPE STRING
*" EXPORTING
*" REFERENCE(DV) TYPE C
*"----------------------------------------------------------------------
* Toma una cadena de numeros, solo numeros (sin .,"·%!$) y calcula el DV
DATA: suma TYPE i,
mult TYPE i,
num TYPE string.
num = cadena.
mult = 2.
suma = 0.
WHILE num <> 0.
suma = suma + num MOD 10 * mult.
num = num DIV 10.
mult = mult + 1.
IF mult > 7.
mult = 2.
ENDIF.
ENDWHILE.
num = 11 - suma MOD 11.
IF num = 10.
dv ='K'.
ELSEIF num = 11.
dv = '0'.
ELSE.
MOVE num TO dv.
ENDIF.
ENDFUNCTION.
It should return a number. I guess that i got a dump in the MOD. How can i solve that problem?? Any ideas??
Regards
Miguel
‎2011 Sep 27 5:01 PM
Hi
You can use the float number (type F) instead of integer
Max
‎2011 Sep 27 5:01 PM
Hi
You can use the float number (type F) instead of integer
Max
‎2011 Sep 27 6:05 PM
‎2011 Sep 27 6:12 PM
Hi
I've tried to run this and it seems to work fine:
DATA: SUMA TYPE F,
MULT TYPE F,
NUM TYPE STRING.
DATA: NUM_F TYPE F.
DATA: DV TYPE C.
NUM = '0200000005500002133200000154700076945190'.
MOVE NUM TO NUM_F.
MULT = 2.
SUMA = 0.
WHILE NUM_F <> 0.
SUMA = SUMA + NUM_F MOD 10 * MULT.
NUM_F = NUM_F DIV 10.
MULT = MULT + 1.
IF MULT > 7.
MULT = 2.
ENDIF.
ENDWHILE.
NUM_F = 11 - SUMA MOD 11.
IF NUM_F = 10.
DV ='K'.
ELSEIF NUM_F = 11.
DV = '0'.
ELSE.
MOVE NUM_F TO DV.
ENDIF.
WRITE DV.Max
‎2011 Sep 27 6:16 PM
‎2011 Sep 27 6:19 PM
Hi
look
check the result with this data:
value = '011004455010010010116000005670', result is = 4
value = '021704490010010120516000005000', result is = 3
more easy
value = '15292975', result is = 7
I need the string up to 40 numbers, with 30 is working and with less also. But a big number get dumps
i changed the program..everything, it doest work, thanks anyway, trying to fix this issue.
Regards
‎2011 Sep 27 6:19 PM
‎2011 Sep 27 6:25 PM
Yes,
and with '0200000005500002133200000154700076945190', it gives 0...
and with '02000000055000021332000001547000769451908711234001' it gives 5...
it even works with a 80 len string
kr,
m.
Edited by: Manu D'Haeyer on Sep 27, 2011 7:26 PM
‎2011 Sep 27 6:29 PM
Hi Manu.
When i changed the data as you said
DATA: suma TYPE f,
mult TYPE i,
num TYPE f.
the result of value = '011004455010010010116000005670' it gives me DV = 5.0000000000000000E+00
And it should be DV = 4
Am I doing sth wrong???
Regards
Edited by: Miguel Alvear on Sep 27, 2011 7:30 PM
‎2011 Sep 27 6:34 PM
DATA: RESULT TYPE I.
DATA: DV(10) TYPE C.
NUM = '11004455010010010116000005670'.
MOVE NUM TO NUM_F.
MULT = 2.
SUMA = 0.
WHILE NUM_F <> 0.
SUMA = SUMA + NUM_F MOD 10 * MULT.
NUM_F = NUM_F DIV 10.
MULT = MULT + 1.
IF MULT > 7.
MULT = 2.
ENDIF.
ENDWHILE.
NUM_F = 11 - SUMA MOD 11.
IF NUM_F = 10.
DV ='K'.
ELSEIF NUM_F = 11.
DV = '0'.
ELSE.
MOVE NUM_F TO RESULT.
MOVE RESULT TO DV.
ENDIF.
WRITE DV.I've changed the program in order to convert the result in a integer number before moving it into a char.
Now if I run the program 011004455010010010116000005670, the result is 2
Max
‎2011 Sep 27 6:35 PM
Well I guess you loose some precision with your DIV statement...
Try with:
num = num / 10.
and then, after looping:
num = 11 - suma MOD 11.
num = ceil( num ).
But I must say I don't really understand what you are trying to do here
kr,
m.
Edited by: Manu D'Haeyer on Sep 27, 2011 7:36 PM
‎2011 Sep 27 6:40 PM
Hi
Yes Manu is right
It's not clear the logic of your algoritm, so which result you need to get, all we can say it's use a number type float in order to avoid the dump.
Max
‎2011 Sep 27 6:45 PM
Hi guys.
The logic of the algoritm is ok, it is working with data type i. The result DV is also ok.
But the problem is that the value if bigger 40 lenght numbers and then
1.- get dump overflow
2.- if i changed to type F, the result is different than if i do it with type i...
that's my issue.
Regards
‎2011 Sep 27 6:48 PM
With '011004455010010010116000005670' and a CEIL statement it gives 4. Is that correct?
Damn I want to understand now...:)
Kr,
m.
‎2011 Sep 27 6:52 PM
Hi,
Yes correct
value=011004455010010010116000005670, DV = 4
value=011157638010010093416000005000, DV = 0
value=010037221010010102116000008050, DV = 1
value=021704490010010120516000005000, DV = 3
value=021706259010010111516000005000, DV = 4
value=041979446010010133316000005000, DV = 1
All of those are ok with the type i, if you change it to float F, it changes...it doesnt have to change.
but the number that the logic will use is longer than 30 as i can use with type i,
if i put a value long 40, using type i, death....and if i change it to type F, also death, the result is not OK
Regards
Trhanks for the help
‎2011 Sep 27 6:55 PM
this issue i thought that it was simple to solve, but it gets more and more complicated...
heheeh
check the first code that i put, the original with type i, use it with the values that i put as samples.
then change the data with type F, use the values...the result is wrong.
Regards
‎2011 Sep 27 7:06 PM
Yes indeed results are different... strange algorithmn you've built up!
Anyway, a last idea perhaps, could you not split the string to work on them separately...?
Well, which you luck!
Kr,
m.
‎2011 Sep 27 7:09 PM
Try with type DECFLOAT34...
edit: oh no... not correct either... different however... That's crasy, a result different per type
Kr,
m.
Edited by: Manu D'Haeyer on Sep 27, 2011 8:09 PM
‎2011 Sep 28 9:14 AM
Hi
The problem is type F doesn't save all integer part, but always the first 16 or 17 number, I means so the result will be different, but probably (you need to use only integer number) you can simple use the type N.
I've changed my code using a type N long 50 char:
PARAMETERS: P(50) TYPE C.
DATA: SUMA(50) TYPE N,
MULT(50) TYPE N,
NUM_C(50) TYPE N,
NUM TYPE STRING.
DATA: DV TYPE STRING.
NUM = P.
MOVE NUM TO NUM_C.
MULT = 2.
SUMA = 0.
WHILE NUM_C <> 0.
SUMA = SUMA + NUM_C MOD 10 * MULT.
NUM_C = NUM_C DIV 10.
MULT = MULT + 1.
IF MULT > 7.
MULT = 2.
ENDIF.
ENDWHILE.
NUM_C = 11 - SUMA MOD 11.
IF NUM_C = 10.
DV ='K'.
ELSEIF NUM_C = 11.
DV = '0'.
ELSE.
MOVE NUM_C TO DV.
ENDIF.
WRITE DV.I've run it with all values you've have posted:
value=011004455010010010116000005670, DV = 4
value=011157638010010093416000005000, DV = 0
value=010037221010010102116000008050, DV = 1
value=021704490010010120516000005000, DV = 3
value=021706259010010111516000005000, DV = 4
value=041979446010010133316000005000, DV = 1
And I get the result expected.
Now the problem could be to delete the leading zero in the result stored in DV, but this is simple to be solved
Max
‎2011 Sep 28 9:28 AM
Hi Max,
Was the first thing I tested... It works yes, but not for a 40 length string, which was the issue...
I've nearly gone crazy with this, don't think there is a solution without changing the logic
Kr,
m.
‎2011 Sep 28 12:41 PM
Hello guys
thanks a lot for your help and effort.
I was able to change the logic of the program and now it works even with 1000 characters and even more.
I'm posting the code, so you can try it
FUNCTION zcalculo_dv.
*"----------------------------------------------------------------------
*"*"Interfase local
*" IMPORTING
*" REFERENCE(CADENA) TYPE STRING
*" EXPORTING
*" REFERENCE(DV) TYPE C
*"----------------------------------------------------------------------
* Toma una cadena de numeros, solo numeros (sin .,"·%!$) y calcula el DV
DATA: suma TYPE i,
mult TYPE i,
largo TYPE i,
num type i,
dig type i.
largo = strlen( cadena ).
mult = 2.
suma = 0.
WHILE largo <> 0.
largo = largo - 1.
dig = cadena+largo(1).
suma = suma + dig * mult.
mult = mult + 1.
IF mult > 7.
mult = 2.
ENDIF.
ENDWHILE.
num = 11 - suma MOD 11.
IF num = 10.
dv ='K'.
ELSEIF num = 11.
dv = '0'.
ELSE.
dv = num.
ENDIF.
ENDFUNCTION.
rather than use the whole value, now I'm using just each character separately and it works.
Regards
‎2011 Sep 28 12:42 PM
Hello
thanks for the help and the effort.
I changed the logic of the code, have a look it, now it works fine.
Regards
Miguel
‎2011 Sep 28 12:46 PM