Migrar COBOL COMP-3 sin perder un céntimo
Una migración COBOL COMP-3 falla si cambian escala, signos, redondeo o bytes no válidos. Modele el contrato y compruebe cada importe.

Una reescritura de software monetario tiene un solo umbral de aceptación: la misma entrada válida debe producir el mismo importe, signo, estado y representación almacenada cuando esa representación siga formando parte de una interfaz. Una diferencia de un céntimo no es un defecto cosmético. En un millón de registros puede cambiar el total de un libro mayor, una cola de excepciones, un tramo de interés o el archivo que acepta un programa posterior.
La suposición peligrosa es que un campo COBOL se corresponde con un tipo de un lenguaje moderno. No es así. El significado procede de PICTURE, USAGE, las opciones del compilador, las sentencias aritméticas, los campos receptores, el diseño del archivo y, a veces, décadas de datos incorrectos tolerados. PIC S9(7)V99 COMP-3 describe un coeficiente entero con signo, una escala implícita de dos y un contrato de almacenamiento empaquetado. Tratarlo como un número genérico descarta al menos la mitad de esa información.
He visto equipos dedicar más tiempo a discutir decimal frente a double que a rastrear el MOVE que realmente elimina decimales. Esa discusión empieza demasiado tarde. Primero hay que recuperar el contrato numérico. Después se elige una representación de destino capaz de exigirlo y se ejecutan ambos sistemas con el mismo tráfico hasta explicar cada diferencia.
La cláusula PICTURE forma parte del valor
La cláusula PICTURE indica el número de dígitos, la escala, la posibilidad de signo y, a veces, posiciones de escala que no ocupan almacenamiento. Ningún dato de esa lista es solo formato.
Veamos estas declaraciones:
01 INVOICE-AMOUNT PIC S9(7)V99 COMP-3.
01 TAX-RATE PIC S9(3)V9(4) COMP-3.
01 WHOLE-DOLLARS PIC S9(9) COMP-3.
01 SMALL-RATIO PIC SV9(6) COMP-3.
V es un punto decimal supuesto. No existe un byte para él en memoria ni en disco. INVOICE-AMOUNT almacena nueve dígitos decimales y un signo, y su coeficiente 123456789 significa 1234567.89. TAX-RATE usa escala cuatro. WHOLE-DOLLARS tiene escala cero. SMALL-RATIO no tiene posiciones enteras, así que el coeficiente 123456 significa 0.123456.
Un inventario de migración debe registrar como mínimo (signed, precision, scale, usage, byte length) para cada elemento numérico. Conserve también la declaración original y el diseño del registro que lo contiene. Los copybooks usan REDEFINES, OCCURS, nombres de condición y movimientos de grupo, de modo que un campo no siempre puede interpretarse sin sus bytes vecinos.
El símbolo P necesita un tratamiento aparte. Describe posiciones de escala supuestas que no se almacenan. La documentación de IBM Enterprise COBOL ofrece ejemplos como PPP999, cuyos dígitos almacenados representan valores entre cero y .000999, y S999PPP, cuyos valores distintos de cero avanzan en miles. Un mapeador que solo cuenta dígitos almacenados pierde la escala aritmética. No deduzca un DECIMAL(p,s) de la longitud en bytes.
Genere un catálogo legible por máquinas en vez de una hoja de cálculo que terminará separándose del código. Una entrada útil tiene este aspecto:
{
"qualifiedName": "CLAIM-REC.PAID-AMOUNT",
"picture": "S9(7)V99",
"usage": "COMP-3",
"bytes": 5,
"precision": 9,
"scale": 2,
"signed": true,
"storage": "packed-decimal"
}
Este artefacto es el principio del contrato de reescritura. También detecta un error habitual del analizador: nueve dígitos en decimal empaquetado necesitan cinco bytes, porque el último medio byte contiene el signo.
Resuelva los alias antes de asignar el significado. Una rama REDEFINES puede tratar los mismos cinco bytes como un importe en un tipo de transacción y como relleno o fecha en otro. El discriminador que selecciona la rama forma parte del contrato numérico. Si la nueva capa de entrada decodifica enseguida todas las ramas posibles, puede rechazar registros válidos porque unos bytes numéricos en un diseño son texto en otro. Registre la condición de control, no solo los desplazamientos superpuestos.
Las operaciones de grupo exigen atención por el motivo contrario. MOVE OLD-GROUP TO NEW-GROUP copia bytes sin aplicar reglas de conversión numérica de elementos. Sustituirlo por un mapeo campo a campo puede normalizar signos, cambiar el relleno o decodificar un campo que el origen nunca consultó. Clasifique cada uso como operación de bytes u operación numérica antes de declarar equivalente un objeto tipado.
Los bytes COMP-3 necesitan un decodificador
El decimal empaquetado guarda dos dígitos decimales por byte, salvo el nibble bajo del último byte, que contiene el signo. El entorno de destino debe validar y decodificar esos nibbles de forma explícita en cada límite externo.
Para PIC S9(5)V99 COMP-3, el valor -12345.67, cuyo coeficiente es -1234567, puede aparecer así:
12 34 56 7D
Lea los nibbles como 1 2 3 4 5 6 7 D. Los primeros siete son dígitos. La D final indica negativo. Un valor positivo convencional termina en C; los datos empaquetados sin signo suelen terminar en F. Los sistemas reales pueden contener otros códigos según las opciones del compilador y la ruta que creó los datos. Por eso el decodificador necesita una política declarada, no una conversión hexadecimal permisiva.
La longitud en bytes para n dígitos almacenados es floor(n / 2) + 1. Si el número de dígitos es par, el primer nibble es relleno. También importa al validar. IBM documenta que NUMCHECK(PAC) comprueba dígitos y signos empaquetados cuando los campos actúan como emisores y, con un número par de dígitos, también los bits no usados. El nuevo decodificador debe decidir si un relleno incorrecto rechaza el registro, lo envía a cuarentena o reproduce una tolerancia histórica documentada.
Este pseudocódigo hace visible el límite:
decodePacked(bytes, precision, scale, signed):
nibbles = splitEachByte(bytes)
signNibble = nibbles.removeLast()
if precision is even:
require nibbles.removeFirst() == 0
require count(nibbles) == precision
require every nibble is between 0 and 9
sign = decodeSign(signNibble, signed, configuredSignPolicy)
coefficient = sign * decimalDigitsToInteger(nibbles)
return FixedDecimal(coefficient, scale)
Mantenga el coeficiente como entero y la escala como metadato. Así 123.40 sigue siendo distinto de un valor flotante sin escala aunque una pantalla muestre luego 123.4. También permite que un codificador reproduzca exactamente registros de ancho fijo.
Escriba el codificador por separado y pruebe encode(decode(bytes)) con cada entrada canónica válida. Pruebe también las entradas no canónicas aceptadas por la política. La equivalencia numérica puede permitir normalizar un signo positivo F a C, pero la paridad de bytes fallará si un consumidor espera la forma original. Si el viaje de ida y vuelta debe ser exacto, conserve el código de signo original o todo el campo bruto junto al número decodificado.
No permita que el decodificador devuelva cero después de un error. Algunas bibliotecas de conversión lo hacen si nadie comprueba el estado, y convierten dinero mal formado en un importe legítimo. Devuelva un resultado etiquetado que obligue al llamador a tratar los estados válido, no válido y aplazado. El sistema de tipos debe dificultar el cálculo accidental con bytes sin decodificar.
El cero negativo merece una prueba. Una entrada empaquetada o zonificada puede tener signo negativo y todos sus dígitos a cero. La mayoría de cálculos comerciales consideran iguales -0.00 y 0.00, pero quizá no un archivo de salida idéntico byte a byte, un flujo de auditoría o una rama sensible al signo. Decida si la decodificación lo normaliza, conserva un indicador de signo o guarda los bytes originales para el viaje de vuelta. El silencio no es una política.
El signed overpunch es otro contrato
El signed overpunch pertenece al decimal zonificado o a datos numéricos DISPLAY, no a COMP-3, aunque ambos formatos introduzcan un signo en una posición de dígito. Confundirlos corrompe valores mientras produce caracteres que parecen razonables.
En decimal zonificado EBCDIC, cada dígito ocupa un byte. Con overpunch final, el nibble alto del último byte de dígito lleva el signo y el nibble bajo lleva el último dígito. Un 123 positivo puede acabar con una zona positiva, mientras -123 usa una zona negativa. Convertidos a caracteres según tablas conocidas, esos bytes pueden parecer letras o llaves. Esa forma visible es una convención de codificación, no el valor numérico.
La declaración del campo y la codificación del archivo deben permanecer unidas. Un analizador ASCII que ve 12L no puede deducir con seguridad menos tres sin saber qué tabla de overpunch lo creó. Una conversión de EBCDIC a Unicode anterior a la decodificación numérica también puede destruir los bits de zona o mapearlos a caracteres que rechaza un analizador decimal genérico.
Decodifique en este orden:
- Corte el registro según su diseño de bytes antes de que la conversión de caracteres cambie los desplazamientos.
- Aplique la página EBCDIC declarada a los campos de texto, pero envíe los bytes DISPLAY numéricos a un decodificador de decimal zonificado.
- Valide cada zona de dígito y el conjunto de signos permitido.
- Devuelva la misma representación de coeficiente y escala que usa el decimal empaquetado.
- Conserve los bytes brutos de los rechazos para que un operador identifique al productor real.
SIGN IS LEADING, SIGN IS TRAILING y SIGN IS SEPARATE cambian el contrato. Un signo separado consume su propia posición; un signo overpunch no. Los analizadores de copybooks que reducen todos los DISPLAY con signo a una regla desplazan los límites del registro o pierden el signo.
Hay una unificación útil: tras la decodificación, el decimal empaquetado y el zonificado pueden compartir la representación de dominio. No deben compartir el decodificador de frontera. Los decodificadores separados alejan las reglas de almacenamiento de los cálculos y ofrecen errores precisos como invalid packed digit at byte 3 en lugar de number format error.
Los decimales exactos no bastan
Use coeficientes enteros, tipos de punto fijo o numéricos de base de datos para el dinero. Nunca pase un decimal COBOL por coma flotante binaria, ni siquiera temporalmente como número JSON o celda de una hoja, porque muchas fracciones decimales no tienen representación binaria exacta.
El mapeo de destino debe responder a las operaciones y al rango observados. S9(7)V99 COMP-3 puede usar un coeficiente con signo de 64 bits y escala dos solo después de demostrar que caben los productos intermedios. Los valores cercanos a 31 dígitos suelen necesitar un entero de precisión arbitraria. En la base, use DECIMAL(p,s) o NUMERIC(p,s) después de probar redondeo y desbordamiento. En límites de red o JSON, envíe cadenas decimales con reglas de escala explícitas para que los consumidores no las conviertan a flotante.
Go no tiene un decimal fijo de precisión arbitraria integrado. Se pueden guardar céntimos en int64 si el cálculo completo demuestra el rango, o encapsular math/big.Int como coeficiente con escala controlada. Rust puede usar aritmética entera comprobada o una biblioteca decimal cuya precisión y modos de redondeo hayan sido revisados. number en TypeScript es coma flotante binaria; use cadenas, bigint escalado o una implementación decimal probada para dinero. numeric en PostgreSQL es exacto, pero la aplicación sigue decidiendo cuándo reducir la escala.
Demuestre el rango con los intermedios, no solo con los campos almacenados. Un importe de nueve dígitos multiplicado por una tasa de siete puede requerir muchos más antes de dividir o cambiar de escala. COBOL puede mantener ese intermedio con una precisión elegida por sus reglas aritméticas y las opciones del compilador. Un int64 de destino puede contener cada entrada y aun así desbordarse al multiplicarlas.
Distinga también la escala de almacenamiento de la unidad comercial. PIC S9(7)V99 suele significar moneda en céntimos, pero no indica qué moneda, si se admiten fracciones de céntimo durante el cálculo ni si el valor es un impuesto, una tasa o un importe. Lleve esos significados a tipos de dominio cuando el programa los revele. Money, Rate y Quantity no deben combinarse solo porque todos usen un coeficiente decimal.
No use el esquema de base de datos como primera y única especificación. Una columna ampliada con los años puede aceptar valores que no caben en COBOL. Una columna más estrecha puede mostrar que una interfaz ya redondeaba antes de guardar. Mapee declaraciones, sentencias, diseños de registro y restricciones de base como un único flujo numérico.
Defina las API aritméticas alrededor del dominio en lugar de exponer por todas partes un decimal genérico. Un importe puede sumarse a otro de la misma unidad. Una tasa puede multiplicarlo y producir un intermedio de mayor escala. Un reparto necesita una regla para el resto, porque dividir 10.00 entre tres no entrega los mismos céntimos a todos. Estas restricciones revelan reglas comerciales que una biblioteca permisiva dejaría eludir.
La serialización también necesita contrato. Decida si la escala dos siempre emite 12.30, si admite signo más, si prohíbe notación exponencial y cuántos dígitos acepta un consumidor. Una cadena JSON evita la conversión binaria dentro del servicio, pero no impide que un navegador, mapeador de mensajes o cargador analítico la convierta después. Las pruebas de contrato deben cruzar el límite real del consumidor.
El redondeo ocurre en los campos receptores
COBOL vincula el redondeo a sentencias aritméticas y campos receptores. Reproducir el tipo final sin cada transición de escala genera otros céntimos. La presencia o ausencia de ROUNDED es comportamiento observable.
Veamos un cálculo de tasa:
01 WS-BASE PIC S9(7)V99 COMP-3.
01 WS-RATE PIC S9(2)V9(5) COMP-3.
01 WS-FEE PIC S9(7)V99 COMP-3.
COMPUTE WS-FEE ROUNDED = WS-BASE * WS-RATE
Con WS-BASE = 100.00 y WS-RATE = 0.01255, el producto exacto es 1.2550000. Pasarlo a escala dos con redondeo ordinario al más cercano produce 1.26. Sin ROUNDED, se truncan las posiciones descartadas y se guarda 1.25. Una reescritura que aplique en todas partes redondeo al par puede producir 1.26 en algunos empates y 1.24 en otros donde el modo COBOL elegido se alejaría de cero. Obtenga la regla real del compilador, el dialecto, la sentencia y las pruebas.
No disperse llamadas a round(2) por el código comercial traducido. Modele el cambio de escala como una operación con semántica nombrada:
rescale(value, targetScale, mode)
modes: truncate, nearestAway, nearestEven, floor, ceiling
Anote cada arista del flujo recuperado que pierda escala. Incluye receptores aritméticos, sentencias MOVE, llamadas con parámetros más estrechos, asignaciones de base, campos de informe y registros de salida. Un MOVE puede eliminar céntimos aunque el cálculo conservara cuatro decimales.
El signo cuenta al truncar. Truncar -1.259 hacia cero da -1.25; aplicar suelo matemático da -1.26. Los lenguajes discrepan en división y resto negativos, así que pruebe la implementación en vez de suponer que un atajo entero se comporta como COBOL.
Los errores de tamaño también forman parte del resultado. ON SIZE ERROR puede tomar una rama si el receptor no admite el valor. Otros caminos pueden cortar dígitos altos o depender de un comportamiento del compilador que el destino debería rechazar. El registro de paridad debe indicar si el origen tomó esa rama, no solo el número almacenado.
Una sentencia aritmética puede tener varios receptores con PICTURE distintos. COBOL aplica el resultado según la capacidad y la cláusula de redondeo de cada uno. Calcular una vez en el destino más estrecho y copiar a los demás pierde información antes que el origen. Calcule con la precisión intermedia recuperada y cambie la escala por separado en cada receptor.
Las reglas monetarias pueden exigir algo distinto de dos decimales. Existen redondeo de efectivo, monedas sin unidad menor y cálculos con fracciones de céntimo, pero el copybook no elige una política. Recupérela de sentencias, tablas y salidas. No añada un Money.round() universal suponiendo que todas las llamadas quieren lo mismo.
La precisión intermedia cambia el resultado
El orden de evaluación, las opciones aritméticas del compilador y los campos temporales pueden cambiar el último céntimo aunque origen y destino usen decimales exactos. Aritmética exacta no significa aritmética ilimitada.
Compare estas formas:
A = roundToCents(BASE * RATE)
B = roundToCents(roundToScale4(BASE * RATE_PART_1) +
roundToScale4(BASE * RATE_PART_2))
Están relacionadas algebraicamente, pero no tienen por qué ser iguales numéricamente. El origen puede redondear cada componente a un campo de trabajo antes de sumar. Una reescritura que fusione la expresión y redondee una vez cambia el programa. Eliminar los campos de trabajo COBOL antes de establecer paridad produce pequeñas diferencias difíciles de rastrear.
La documentación de IBM Enterprise COBOL distingue ARITH(COMPAT) y ARITH(EXTEND). La primera limita los operandos decimales a 18 dígitos; la segunda permite 31 y cambia la capacidad de los intermedios de punto fijo. IBM también avisa de que NUMVAL puede implicar valores aproximados y que la opción aritmética afecta al resultado. Un campo decimal en reposo puede pasar por flotantes o intermedios de otros tamaños durante una conversión.
Inventaríe la configuración de compilador y ejecución de cada módulo. El mismo código fuente compilado con opciones distintas no garantiza el mismo contrato ejecutable. Registre ARITH, NUMPROC, TRUNC, dialecto, versión y ajustes pertinentes. Si faltan datos de compilación, cree programas sonda y ejecute entradas límite en un compilador compatible con producción.
Una matriz útil incluye empates positivos y negativos, coeficientes máximos, cero con cada signo aceptado, productos que necesitan un dígito intermedio adicional y divisiones periódicas. Guarde bytes de entrada, salida DISPLAY, bytes resultantes, códigos de retorno y marcas de rama. Esos programas pequeños resuelven antes las discusiones sobre lo que COBOL hace "normalmente".
Conserve el orden de evaluación en la primera versión correcta. Cuando la paridad permanezca limpia, simplifique expresiones de una en una. Cada cambio debe demostrar que preserva las salidas en tráfico grabado y límites generados.
Los datos numéricos inválidos también migran
Los archivos de producción suelen contener bytes que contradicen sus copybooks, y el programa antiguo puede tolerarlos hasta que una operación fuerce la validación. Una reescritura que limpie todo en silencio puede ser tan incorrecta como otra que falle en el primer registro sucio.
IBM indica que el compilador suele suponer que los datos cumplen PICTURE y USAGE. NUMCHECK(ZON,PAC) puede añadir comprobaciones cuando campos zonificados o empaquetados actúan como emisores. Los signos válidos pueden depender de NUMPROC y de opciones de instalación. Dos programas pueden leer el mismo registro y mostrar el defecto en puntos distintos porque uno compara el campo numéricamente y otro mueve el grupo como bytes.
Sigamos un fallo. Un campo empaquetado entrante contiene 12 34 5A: nibbles de dígitos válidos, pero un signo rechazado por la política activa. El proceso nocturno copia el grupo a un archivo y termina bien porque nunca trata el campo como número. Más tarde, un total de cierre mensual lo usa como emisor, dispara una excepción o comprobación y envía el registro a una cola de operador. Una reescritura que decodifica todo al entrar lo rechaza antes. Otra que acepta cualquier signo de A a F puede sumarlo. Ambas alteraron el comportamiento operativo.
La respuesta correcta es una política de compatibilidad por campo y respaldada por pruebas:
- Los campos estrictos rechazan de inmediato cualquier dígito, relleno o signo inválido.
- Los aplazados conservan bytes brutos y se decodifican en el mismo límite semántico que el origen.
- Las codificaciones toleradas conocidas reciben casos explícitos y fixtures con nombre.
- Los rechazos llevan identidad de registro, campo, desplazamiento y entrada hexadecimal.
No haga de la permisividad el valor predeterminado. Primero ejecute el origen con los diagnósticos disponibles en un entorno representativo, muestree archivos reales y localice cada productor. Los datos sucios suelen revelar una interfaz no documentada, no una costumbre del mainframe.
Esta distinción también cambia el despliegue. Una diferencia numérica con datos válidos es un defecto de reescritura. Un registro inválido recién detectado puede ser defecto del dato, del productor o una diferencia de compatibilidad deliberada. El equipo necesita contadores y responsables distintos o el panel de paridad se convertirá en una discusión sobre un total rojo.
La paridad debe comparar más que totales
Un arnés de paridad debe repetir las mismas transacciones en origen y destino, y comparar campos, ramas, errores y bytes serializados antes de los totales de lote. Dos errores opuestos pueden ocultarse bajo un agregado idéntico.
El tráfico de producción grabado aporta combinaciones realistas, pero rara vez cubre límites numéricos. Añada casos generados para cada contrato:
- cero, cero negativo, mínimo, máximo y una unidad fuera del rango;
- cada valor a mitad de camino en cada pérdida de escala, a ambos lados de cero;
- cada signo empaquetado u overpunch aceptado y rechazado;
- dígitos no válidos, relleno, registros cortos y errores de codificación;
- valores que solo desbordan tras multiplicar o alinear escalas.
Para cada caso capture un sobre de comparación como este:
{
"case": "fee-negative-half-cent",
"inputHex": "00001000C000125C",
"source": {
"coefficient": "-126",
"scale": 2,
"status": "OK",
"outputHex": "0000126D"
},
"target": {
"coefficient": "-126",
"scale": 2,
"status": "OK",
"outputHex": "0000126D"
}
}
La forma exacta variará, pero las cadenas para coeficientes que superan el entero seguro del consumidor son deliberadas. Los campos hexadecimales muestran diferencias de signo y relleno. El estado incluye ramas del origen como ON SIZE ERROR, no solo el código de salida del proceso.
Si un lote de un millón de registros difiere en un céntimo, divida primero por rango, después por transacción, campo y operación. Registre operandos sin escalar, escalas, operación, precisión intermedia y modo de ajuste. Una traza que solo diga expected 19.42, got 19.43 deja el trabajo difícil a una persona en el peor momento.
Ejecute tres niveles de comparación. La paridad numérica comprueba coeficientes tras alinear escalas declaradas. La de comportamiento comprueba decisiones, excepciones y registros posteriores. La de bytes comprueba interfaces fijas que deben seguir idénticas. No exija esta última a una API nueva cuyo formato pueda cambiar sin riesgo, ni acepte solo la numérica en un extracto regulado leído por desplazamientos.
Trate las exclusiones de comparación como código. Si difieren marcas de tiempo, secuencias o formatos rediseñados, normalice solo esos campos y revise la regla como lógica de producción. Una opción amplia de "ignorar espacios" puede borrar una posición de signo o un desplazamiento de columna. Cada exclusión necesita responsable y condición de caducidad.
Las puertas de publicación deben informar clases de diferencias, no un porcentaje combinado. Cero diferencias monetarias sin explicar es una puerta razonable aunque queden cambios de interfaz aprobados. Mantenga reproducible el origen hasta que cada diferencia tenga fixture, decisión y prueba de regresión, o el mismo céntimo volverá después de una optimización ajena.
CodeHero usa tráfico de producción grabado en un arnés de paridad por este motivo: que una traducción compile no demuestra que sobreviva el comportamiento decimal. En sistemas grandes, automatice el catálogo de campos y las trazas para que los revisores analicen diferencias en vez de transcribir copybooks.
El contrato de migración debe poder revisarse
El contrato numérico terminado debe permitir rastrear cualquier importe de destino hacia los bytes de origen y hacia delante por cada límite de redondeo. Si solo está en la cabeza del último mantenedor COBOL, la reescritura no está lista.
Exija estos elementos antes de cambiar un flujo monetario:
- Cada campo numérico de origen tiene nombre cualificado, PICTURE, USAGE, rango de bytes, codificación, precisión, escala y política de signo.
- Cada tipo de destino tiene una demostración escrita del rango que incluye intermedios.
- Cada pérdida de escala nombra su redondeo o truncado y la sentencia de origen que lo fijó.
- Los datos inválidos tienen fixtures para casos aceptados, rechazados, aplazados y de cero negativo.
- La suite compara resultados numéricos, de comportamiento y de bytes donde importa cada uno.
Guarde este contrato junto al código nuevo y genere automáticamente todo lo posible. Un revisor debe poder cuestionar S9(11)V9(6) -> int64 con los operandos máximos y ver la respuesta, no aceptar una nota que diga "cabe".
Después del cambio, conserve métricas de límite separadas para fallos de decodificación, desbordamientos, reducciones de escala y diferencias de paridad. No escriba valores de cuentas ni registros completos en logs generales. Identificadores de campo y operación, referencias seguras y coeficientes ocultos suelen bastar para localizar el fallo sin crear otro problema de datos.
El criterio para el dinero es deliberadamente estricto. Cada céntimo necesita procedencia: dígitos de origen, interpretación del signo, escala, operaciones intermedias y regla final de cambio de escala. Cuando la reescritura puede mostrar esa cadena para un fallo y demostrarla en el corpus, la representación antigua puede desaparecer sin llevarse su comportamiento.
Preguntas frecuentes
¿Qué es COMP-3 en COBOL?
COMP-3 es almacenamiento decimal empaquetado. Coloca dos dígitos en casi todos los bytes y reserva el último medio byte para el signo, mientras PICTURE aporta precisión y escala.
¿Cuántos bytes usa un campo COMP-3?
Para n dígitos, use floor(n / 2) + 1 bytes. El medio byte adicional contiene el signo y un número par deja un nibble inicial de relleno que también debe validarse.
¿La V de una PICTURE COBOL ocupa un byte?
No. V marca un punto decimal supuesto sin almacenamiento, por lo que S9(5)V99 guarda siete dígitos y un signo con escala dos.
¿Se puede migrar dinero COBOL a double o float?
No de forma segura. La coma flotante binaria no representa exactamente muchas fracciones decimales, y una conversión temporal puede cambiar el redondeo aunque luego vuelva a un tipo decimal.
¿Signed overpunch es lo mismo que COMP-3?
No. Overpunch integra el signo en los bits de zona de un dígito DISPLAY, mientras COMP-3 guarda dígitos en nibbles y reserva el último para el signo.
¿Qué nibble de signo significa negativo en decimal empaquetado?
D es el signo negativo convencional, C suele significar positivo y F aparece a menudo en datos sin signo. Trate el conjunto aceptado como política del compilador y la interfaz, porque producción puede contener otros códigos.
¿COBOL redondea automáticamente los importes?
No existe una regla universal. Depende de la sentencia, el receptor y la presencia de ROUNDED; sin esa cláusula, la pérdida de escala suele truncarse.
¿Por qué un decimal exacto puede diferir de COBOL?
Los tipos exactos aún tienen precisión, orden de evaluación y reglas de cambio de escala. Cambiar un temporal, fusionar expresiones o redondear una sola vez puede mover el último céntimo.
¿Cómo debe migrarse el cero negativo?
Decida si normalizarlo, conservar un indicador de signo o guardar los bytes para el viaje de vuelta. La igualdad numérica no resuelve una rama sensible al signo ni una salida fija.
¿Qué demuestra que una reescritura monetaria COBOL es correcta?
Repita las mismas entradas y compare coeficientes, escalas, ramas, errores y bytes necesarios. Añada límites generados porque el tráfico grabado rara vez contiene cada empate, desbordamiento, signo o campo incorrecto.