Ver la Versión Completa : [Compilador] String para Decimal
Joseg
5 de mayo de 2022, 12:05
Necessito de achar um valor único de uma string, para criar uma chave, já que chaves primarias ou alternadas tem um limite máximo de 255 bytes.
Calcular o valor ASCII do mesmo poderia ser uma possibilidade...
Esta função:
FUNCTION ORD (argument-1)
é uma possiblidade mas necessito de percorrer uma string grande, tipo:
01 wmyvar pic x(3000).
fica lento.
Conhecem alguma alternativa?
Gracias,
Kuk
5 de mayo de 2022, 15:42
fica lento.
¿Cómo lo haces? Prueba algo así:
01 wmyvar pic x(3000).
01 filler redefines wmyvar.
05 byte occurs 3000 pic 9(2) comp-5.
01 idx-1 pic 9(4) comp-5.
01 suma pic 9(9) comp-5.
procedure division.
move 1 to idx-1
move 0 to suma
perform until idx-1 > length of wmyvar
add byte(idx-1) to suma
add 1 to idx-1
end-perform
También mira esto a ver si dura menos, el cálculo será diferente pero puede servir igual creo:
01 wmyvar pic x(3000).
01 filler redefines wmyvar.
05 byte occurs 1500 pic 9(4) comp-5.
01 idx-1 pic 9(4) comp-5.
01 suma pic 9(9) comp-5.
procedure division.
move 1 to idx-1
move 0 to suma
perform until idx-1 > 1500
add byte(idx-1) to suma
add 1 to idx-1
end-perform
01 wmyvar pic x(3000).
01 filler redefines wmyvar.
05 byte occurs 750 pic 9(9) comp-5.
01 idx-1 pic 9(4) comp-5.
01 suma pic 9(18) comp-5.
procedure division.
move 1 to idx-1
move 0 to suma
perform until idx-1 > 750
add byte(idx-1) to suma
add 1 to idx-1
end-perform
Joseg
10 de mayo de 2022, 13:50
Ainda não tenho a solução para o problema.
Pretendia que a string:
"101.10.01"
fosse SEMPRE diferente de:
"101.10.10"
...e tenho casos em que o cálculo dá o mesmo valor.
Gracias por qualquer ajuda.
¿Cómo lo haces? Prueba algo así:
01 wmyvar pic x(3000).
01 filler redefines wmyvar.
05 byte occurs 3000 pic 9(2) comp-5.
01 idx-1 pic 9(4) comp-5.
01 suma pic 9(9) comp-5.
procedure division.
move 1 to idx-1
move 0 to suma
perform until idx-1 > length of wmyvar
add byte(idx-1) to suma
add 1 to idx-1
end-perform
También mira esto a ver si dura menos, el cálculo será diferente pero puede servir igual creo:
01 wmyvar pic x(3000).
01 filler redefines wmyvar.
05 byte occurs 1500 pic 9(4) comp-5.
01 idx-1 pic 9(4) comp-5.
01 suma pic 9(9) comp-5.
procedure division.
move 1 to idx-1
move 0 to suma
perform until idx-1 > 1500
add byte(idx-1) to suma
add 1 to idx-1
end-perform
01 wmyvar pic x(3000).
01 filler redefines wmyvar.
05 byte occurs 750 pic 9(9) comp-5.
01 idx-1 pic 9(4) comp-5.
01 suma pic 9(18) comp-5.
procedure division.
move 1 to idx-1
move 0 to suma
perform until idx-1 > 750
add byte(idx-1) to suma
add 1 to idx-1
end-perform
Kuk
10 de mayo de 2022, 15:36
@Joseg, prueba con la última versión, la de byte occurs 750 pic 9(9) comp-5. porque ahí toma 4 bytes con lo cual también tiene en cuenta el orden.
A mi me funciona, mira el ejemplo que has dado da diferente resultado con el método que digo:
PIC X(12) VALUE "101.10.01" --> 00000000002122285203
PIC X(12) VALUE "101.10.10" --> 00000000002139062418
Joseg
10 de mayo de 2022, 16:34
@Joseg, prueba con la última versión, la de byte occurs 750 pic 9(9) comp-5. porque ahí toma 4 bytes con lo cual también tiene en cuenta el orden.
A mi me funciona, mira el ejemplo que has dado da diferente resultado con el método que digo:
PIC X(12) VALUE "101.10.01" --> 00000000002122285203
PIC X(12) VALUE "101.10.10" --> 00000000002139062418
Com um exemplo fica mais fácil testar !
Joseg
10 de mayo de 2022, 16:51
Com um exemplo fica mais fácil testar !
A ordem como os códigos (121-05-10;...) são colocados na string , pode ser um diferenciador.
Kuk
10 de mayo de 2022, 17:44
@Joseg,
MainForm -> EDIT PROCEDURE DIVISION -> NEW, renombra en PRC-CALC
Edita y pega esto:
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 idx-1 pic 9(4) comp-5.
01 wsomamodelos pic 9(18) comp-5.
LINKAGE SECTION.
01 LNK-DATOS.
05 LNK-INPUT PIC X(3000).
05 filler redefines LNK-INPUT.
10 byte occurs 750 pic 9(8) comp-5.
05 LNK-OUTPUT PIC 9(18).
PROCEDURE DIVISION USING LNK-DATOS.
move 1 to idx-1
move function current-date(5:12) to LNK-OUTPUT
perform until idx-1 > 750
add byte(idx-1) to wsomamodelos
add 1 to idx-1
end-perform
add wsomamodelos to LNK-OUTPUT
display LNK-OUTPUT
Código del botón Nº1:
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 LNK-DATOS.
05 LNK-INPUT PIC X(3000).
05 LNK-OUTPUT PIC 9(18).
PROCEDURE DIVISION.
MOVE "Text" OF CmText1 TO LNK-INPUT
perform 5 times *> PARA TEST RAPIDO
CALL "PRC-CALC" USING LNK-DATOS
end-perform
MOVE LNK-OUTPUT TO "Text" OF CmText3
Código del botón Nº2:
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 LNK-DATOS.
05 LNK-INPUT PIC X(3000).
05 LNK-OUTPUT PIC 9(18).
PROCEDURE DIVISION.
MOVE "Text" OF CmText2 TO LNK-INPUT
CALL "PRC-CALC" USING LNK-DATOS
MOVE LNK-OUTPUT TO "Text" OF CmText4
Joseg
10 de mayo de 2022, 17:58
@Joseg,
MainForm -> EDIT PROCEDURE DIVISION -> NEW, renombra en PRC-CALC
Edita y pega esto:
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 idx-1 pic 9(4) comp-5.
01 wsomamodelos pic 9(18) comp-5.
LINKAGE SECTION.
01 LNK-DATOS.
05 LNK-INPUT PIC X(3000).
05 filler redefines LNK-INPUT.
10 byte occurs 750 pic 9(8) comp-5.
05 LNK-OUTPUT PIC 9(18).
PROCEDURE DIVISION USING LNK-DATOS.
move 1 to idx-1
move function current-date(5:12) to LNK-OUTPUT
perform until idx-1 > 750
add byte(idx-1) to wsomamodelos
add 1 to idx-1
end-perform
add wsomamodelos to LNK-OUTPUT
display LNK-OUTPUT
Código del botón Nº1:
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 LNK-DATOS.
05 LNK-INPUT PIC X(3000).
05 LNK-OUTPUT PIC 9(18).
PROCEDURE DIVISION.
MOVE "Text" OF CmText1 TO LNK-INPUT
perform 5 times *> PARA TEST RAPIDO
CALL "PRC-CALC" USING LNK-DATOS
end-perform
MOVE LNK-OUTPUT TO "Text" OF CmText3
Código del botón Nº2:
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 LNK-DATOS.
05 LNK-INPUT PIC X(3000).
05 LNK-OUTPUT PIC 9(18).
PROCEDURE DIVISION.
MOVE "Text" OF CmText2 TO LNK-INPUT
CALL "PRC-CALC" USING LNK-DATOS
MOVE LNK-OUTPUT TO "Text" OF CmText4
Gracias pela ajuda !!!
Entendo a ideia. Mas não posso usar.
Eu quero mais tarde validar o registo voltando a calcular o valor original tendo por base esta string "121-03-10;121-17-00;121-03-10;121-17-00;121-05-01;", para ver se o registo já existe.
Se a "primary key" não tivesse o limite de apenas 255 bytes (ficheiros ISAM), não tinha este problema. Simplesmente definia como chave única:
01 wmodelosori PIC X(3000).
e tinha o problema resolvido.
Mas como a String pode conter até 3000 bytes tenho que procurar outra solução.
Kuk
10 de mayo de 2022, 20:46
@Joseg, creo que lo he arreglado:
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 idx-1 pic 9(4) comp-5.
01 wsomamodelos pic 9(18) comp-5.
LINKAGE SECTION.
01 LNK-DATOS.
05 LNK-INPUT PIC X(3000).
05 filler redefines LNK-INPUT.
10 byte occurs 750 pic 9(8) comp-5.
05 LNK-OUTPUT PIC 9(18).
PROCEDURE DIVISION USING LNK-DATOS.
move 1 to idx-1
move 0 to LNK-OUTPUT, wsomamodelos
perform until idx-1 > 750
COMPUTE wsomamodelos = wsomamodelos + byte(idx-1) * idx-1
add 1 to idx-1
end-perform
MOVE wsomamodelos to LNK-OUTPUT
display LNK-OUTPUT
Es que estábamos tontos macho, con la SUMA no vale, y lo sabemos desde el cole :D
Propiedad conmutativa de la suma: cambiar el orden de los sumandos no altera la suma
Joseg
11 de mayo de 2022, 11:21
@Joseg, creo que lo he arreglado:
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 idx-1 pic 9(4) comp-5.
01 wsomamodelos pic 9(18) comp-5.
LINKAGE SECTION.
01 LNK-DATOS.
05 LNK-INPUT PIC X(3000).
05 filler redefines LNK-INPUT.
10 byte occurs 750 pic 9(8) comp-5.
05 LNK-OUTPUT PIC 9(18).
PROCEDURE DIVISION USING LNK-DATOS.
move 1 to idx-1
move 0 to LNK-OUTPUT, wsomamodelos
perform until idx-1 > 750
COMPUTE wsomamodelos = wsomamodelos + byte(idx-1) * idx-1
add 1 to idx-1
end-perform
MOVE wsomamodelos to LNK-OUTPUT
display LNK-OUTPUT
Es que estábamos tontos macho, con la SUMA no vale, y lo sabemos desde el cole :D
"Es que estábamos tontos macho, con la SUMA no vale, y lo sabemos desde el cole" :bat: :bat:
Agora si !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!
Muitas muitas gracias Kuk
Joseg
22 de enero de 2026, 18:05
"Es que estábamos tontos macho, con la SUMA no vale, y lo sabemos desde el cole" :bat: :bat:
Agora si !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! !!!!!!
Muitas muitas gracias Kuk
Tengo un problema con este cálculo, y ahora es grave, porque ya hay muchos registros creados.
La suma de la cadena "207.99.99;" es igual a "247.97.99;".
Mi resultado: "000151790274229935".
Mi objetivo es que sea diferente. ¿Hay alguna alternativa?
Gracias,
José
Kuk
22 de enero de 2026, 21:55
@Joseg, nunca he sido un crack de las formulas y algoritmos la verdad, pero me acabo de dar cuenta de otra cosa que sabemos desde el cole y se nos ha escapado...
El cálculo lo hacemos así:
COMPUTE wsomamodelos = wsomamodelos + byte(idx-1) * idx-1
De esta manera, primero se hace la multiplicación.
Si lo hacemos así, con paréntesis, para que primero se haga la suma:
COMPUTE wsomamodelos = (wsomamodelos + byte(idx-1)) * idx-1
Entonces a mi me da 2 valores diferentes:
207.99.99; --> 759816616914665856
247.97.99; --> 257135248213769984
Joseg
22 de enero de 2026, 22:39
@Joseg, nunca he sido un crack de las formulas y algoritmos la verdad, pero me acabo de dar cuenta de otra cosa que sabemos desde el cole y se nos ha escapado...
El cálculo lo hacemos así:
COMPUTE wsomamodelos = wsomamodelos + byte(idx-1) * idx-1
De esta manera, primero se hace la multiplicación.
Si lo hacemos así, con paréntesis, para que primero se haga la suma:
COMPUTE wsomamodelos = (wsomamodelos + byte(idx-1)) * idx-1
Entonces a mi me da 2 valores diferentes:
207.99.99; --> 759816616914665856
247.97.99; --> 257135248213769984
Ahhhhhhh, ok, ok,
Muchas gracias, Kuk. Cambiaré la fórmula. Sin embargo, chatGTP sugirió este ejemplo, lo que garantiza que siempre funciona, independientemente del orden de los dígitos/caracteres.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-TEXTO PIC X(50)
VALUE "207.99.99;247.97.99;".
01 WS-CODE PIC 9(9) VALUE 0.
01 WS-ASCII PIC 9(3).
01 I PIC 9(3).
PROCEDURE DIVISION.
MOVE 0 TO WS-CODE
PERFORM VARYING I FROM 1 BY 1
UNTIL I > FUNCTION LENGTH(WS-TEXTO)
COMPUTE WS-ASCII = FUNCTION ORD(WS-TEXTO(I:1))
COMPUTE WS-CODE = (WS-CODE * 31) + WS-ASCII
COMPUTE WS-CODE = FUNCTION MOD(WS-CODE, 999999999)
END-PERFORM
DISPLAY "CODIGO = " WS-CODE
Kuk
24 de enero de 2026, 20:44
chatGTP sugirió
Yo no me fiaría en este tipo de cosas ;)
Joseg
19 de marzo de 2026, 13:42
Yo no me fiaría en este tipo de cosas ;)
Hola Kuk, esto no es fácil.
El cliente detectó otro error. Los códigos:
105.02.11 y 115.01.11
dan el mismo valor: 298955437302929664.
Creo que hay que tener en cuenta la posición en la que se introducen los dígitos. ¿Puedes ayudarme?
Gracias
Jose
Kuk
20 de marzo de 2026, 10:17
@Joseg, para no reinventar la rueda, vamos a optar por soluciones estándar, como es el caso de OpenSSL: https://es.dll-files.com/libcrypto.dll.html
Con esta solución generamos un HASH, en el caso concreto, el SHA256:
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 strInput PIC X(3000).
01 LK-HASH-RAW PIC X(32).
01 hLib PIC S9(9) COMP-5.
01 ptrSHA256 PROCEDURE-POINTER.
01 ptrINPUT POINTER.
01 nPtrINPUT REDEFINES ptrINPUT PIC S9(9) COMP-5.
01 strLen PIC S9(9) COMP-5.
*-----------------------------------
01 LNK-LEN PIC 9(4) COMP.
01 LNK-INPUT.
05 FILLER PIC X OCCURS 1 TO 1000 DEPENDING ON LNK-LEN.
01 LNK-OUTPUT.
05 LNK-HEX1.
10 LNK-H1 PIC X OCCURS 1 TO 1000 DEPENDING ON LNK-LEN.
05 LNK-HEX2.
10 LNK-H2 PIC X OCCURS 1 TO 1000 DEPENDING ON LNK-LEN.
PROCEDURE DIVISION.
MOVE POW-TEXT OF CmText1 TO strInput
CALL "LoadLibraryA" WITH STDCALL USING BY CONTENT "libcrypto.dll" RETURNING hLib
CALL "GetProcAddress" WITH STDCALL USING BY VALUE hLib, BY CONTENT "SHA256" & X"00" RETURNING ptrSHA256
MOVE FUNCTION ADDR(strInput) TO ptrINPUT
COMPUTE strLen = FUNCTION STORED-CHAR-LENGTH(strInput)
CALL ptrSHA256 WITH STDCALL USING
BY VALUE nPtrINPUT
BY VALUE strLen
BY REFERENCE LK-HASH-RAW
COMPUTE LNK-LEN = FUNCTION STORED-CHAR-LENGTH(LK-HASH-RAW)
MOVE LK-HASH-RAW TO LNK-INPUT
CALL "HEX" USING LNK-LEN, LNK-INPUT, LNK-OUTPUT
MOVE LNK-OUTPUT TO POW-TEXT OF CmText3
Tienes que crear una nueva PROCEDURE y llamarla HEX, su contenido es el siguiente:
ENVIRONMENT DIVISION.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 IDX-1 PIC S9(4) COMP-5.
01 IDX-S PIC S9(4) COMP-5.
01 TBL-HEX PIC X(16) VALUE "0123456789ABCDEF".
01 WS-HEX-1 PIC S9(4) COMP-5.
01 WS-HEX-2 PIC S9(4) COMP-5.
01 WS-BIN PIC X.
01 WS-BIN-2 REDEFINES WS-BIN PIC 9(2) COMP-5.
************************************************** ****************
* LINKAGE SECTION *
************************************************** ****************
LINKAGE SECTION.
01 LNK-LEN PIC 9(4) COMP.
01 LNK-INPUT.
05 FILLER PIC X OCCURS 1 TO 1000 DEPENDING ON LNK-LEN.
01 LNK-OUTPUT PIC X(2000).
************************************************** ****************
* PROCEDURE DIVISION
************************************************** ****************
PROCEDURE DIVISION USING LNK-LEN, LNK-INPUT, LNK-OUTPUT.
MOVE 1 TO IDX-1, IDX-S
PERFORM UNTIL IDX-1 > LNK-LEN
MOVE LNK-INPUT(IDX-1:1) TO WS-BIN
DIVIDE WS-BIN-2 BY 16
GIVING WS-HEX-1 REMAINDER WS-HEX-2
ADD 1 TO WS-HEX-1, WS-HEX-2
MOVE TBL-HEX(WS-HEX-1:1) TO LNK-OUTPUT(IDX-S:1)
ADD 1 TO IDX-S
MOVE TBL-HEX(WS-HEX-2:1) TO LNK-OUTPUT(IDX-S:1)
ADD 1 TO IDX-1, IDX-S
END-PERFORM
GOBACK
.
No olvides lo de ALPHAL(WORD) e incluir la KERNEL32.LIB.
Resultados:
Valor|sha256
105.02.11|45A5AC763720497A3054E1A5C1C24DB458CE0C30 79F9AD2AB9496EAF9EAC087B
115.01.11|2B83108827E847A74B0886AB2E532E3F79988131 A61546499C3B08F32E4DB9F5
207.99.99|8189CCD84246547FD968902606574828E03D332D 2A9D65D9FCA11868303CA8B9
247.97.99|D9DCC2614B2499CCEEF96484C65855258D7CD2AF 8DEA2E5079C7F13860D9C323
¡¡¡Esto ya NO PUEDE fallar!!! :D
Joseg
20 de marzo de 2026, 12:52
Kuk,
Muchas gracias por tu trabajo. Creo que esta es una solución más sólida que podría interesar al resto de la comunidad.
Ya la he probado y parece funcionar bien.
@Joseg, para no reinventar la rueda, vamos a optar por soluciones estándar, como es el caso de OpenSSL: https://es.dll-files.com/libcrypto.dll.html
vBulletin v3.8.7, Derechos ©2000-2026, Jelsoft Enterprises Ltd.