Sobre la implementación de la representación exacta de números o "¿dónde guardar el dinero?"

Introducción

 "¿Dónde guardar el dinero?" este es el título en broma de una publicación que aparece periódicamente en foros informáticos. Esto se refiere a la pregunta: en qué tipo de variables deben almacenarse los resultados de los cálculos de los cálculos financieros y económicos. Por lo general, esta pregunta surge entre los programadores que primero se enfrentan a tales cálculos. Entienden intuitivamente que el redondeo es indeseable o inaceptable aquí. Curiosamente, al mismo tiempo, a menudo recuerdan las leyendas sobre programadores astutos que lograron transferir la diferencia entre el valor exacto y redondeado de los cálculos financieros a su propia cuenta. Es cierto que estas historias se llamaron cuentos de hadas en el libro [1], escrito hace 50 años, e incluso allí solo se trataba de revisiones de sistemas bancarios, cuyos motivos (es decir, revisiones) podrían ser historias similares.





60 . . , - , , «» . «» , . , , «» , .





: 13% 1 30 . «» : 16.9 . «double», 1.68999999999999E-001 , 0.169 IEEE-754 . : ? – . ? , «» , «float» ?





, . «», , DECIMAL C#. [2], « Decimal , . Decimal . ». , , .





, , . , . – , . « » , .. , . DECIMAL C# « FLOAT», , . , .





IA-32 - . . , 64- , , Intel «» . 32- , . - , , , , , . , «» . - , – .





, , PL/1. , «» . , - IA-32 (, IA-16 1978 ) PL/1 . PL/1 [3], . , , 3-4% .





FIXED DECIMAL

PL/1 : FIXED, FLOAT. , «FIXED/FLOAT» ( «/») . , , , «double».





PL/1 FIXED DECIMAL, , , FIXED DECIMAL(15,0) FIXED DECIMAL(12,4) .. . FIXED BINARY, , .





- BCD (Binary Coded Decimal). BCD . BCD . BCD , - , - . FIXED DECIMAL «» p ( 1 15) FLOOR((p+2)/2).





, 12345 5, PL/1 FLOOR((5+2)/2)=3 , 45 23 01. , 999 999 999 999 999. , , ,, 2013 $16,400,000,000,000, FIXED DECIMAL(14,0). , 60, PL/1 .





9 , 9 . , -2 (9-2)+1=8 1 98, 5 98 99 99.





, . – . , - .. , , « » . , 1.3 FIXED DECIMAL(2,1), 0.13 - FIXED DECIMAL(3,2), ( 0.169) FIXED DECIMAL(6,3), «», «» . «» 5, 6, PL/1 p1+p2+1, (a1a2-b1b2)+(a1b2+b1a2)i, .





- , , : , FLOOR/CEIL/TRUNC, .. FIXED DECIMAL . 8 99 ( ).





, . , .





;══════════════════  DECIMAL   ═════════════════
PUBLIC ?DSUOP:                  ;   PL/1
      LEA       ESI,[ESP]+4     ; 1 DECIMAL ( RET)
      MOV       ECX,8           ;  DECIMAL
      CLC                       ; 
      LEA       EDI,[ESI+ECX]   ; 2 DECIMAL

;----   ----

M2187:MOV       AL,[EDI]
      SBB       AL,[ESI]        ;  
      DAS
      STOSB                     ; 
      INC       ESI
      LOOP      M2187

			POP       ECX             ; 
      MOV       ESP,ESI         ; 
      JMP       ECX
      
;══════════════════  DECIMAL   ══════════════════
EXTRN ?DOVER:NEAR

PUBLIC ?DADOP:                  ;   PL/1
      LEA       ESI,[ESP]+4     ; 1 DECIMAL ( RET)
      MOV       ECX,8           ;  DECIMAL
      CLC                       ; 
      LEA       EDI,[ESI+ECX]   ; 2 DECIMAL

;----    DECIMAL   ----

M2283:LODSB
			ADC       AL,[EDI]        ;  
      DAA
      STOSB                     ; 
      LOOP      M2283

;----    ----

      AND       AL,0F0H         ;  
      JZ        @
      CMP       AL,90H          ;   ?
      JNZ       ?DOVER          ;OVERFLOW  DECIMAL
   
;----     ----

@:    POP       ECX             ; 
      MOV       ESP,ESI         ; 
      JMP       ECX
      
      



, - (ADC/SBB) (DAA/DAS), , 64- .





, , , , -, .





, FIXED DECIMAL: (, , ), PL/1 8 . , 15 31, 8 16, 16 31 . .





PL/1

, PL/1, , . FIXED DECIMAL FLOAT(53) – «double» .





test:proc main;

dcl x fixed decimal(6,3);
x=1.3;
x=x*0.13;
put skip data(x);
x=x/0.13;
put skip data(x);

dcl y float(53);
y=1.3;
y=y*0.13;
put skip data(y);
y=y/0.13;
put skip data(y);

end test;
      
      



.





cálculos con valores exactos y aproximados

FIXED DECIMAL , FLOAT - . , , , FIXED DECIMAL, , , « » .





, , PL/1, , , . , . , PL/1 E FLOAT, , . , , 25.0+1/3 , 1/3 (.. 15 ) «». 25.0+10/3 .





, , : . , , .





« », .. , , , PL/1 « 1». , . , [4] «» «». IA-32 , . 64- DAA/DAS , , , :





;---------------  DAA,    X86-64 ------------------

PUBLIC DAA_X86_64:

      PUSH      RDX,RAX
      LAHF
      MOV       EDX,EAX         ;OLD CF  OLD AL
      AND       AH,NOT 1B       ; CF

;----    ----

      TEST      AH,10000B       ;  AF
      JNZ       @
      PUSH      RAX
      AND       AL,0FH
      CMP       AL,9            ;    9
      POP       RAX
      JBE       M2270
@:    ADD       AL,6            ; 
      OR        AH,10000B       ; AF

;----    ----

M2270:TEST      DH,1B           ;  OLD CF
      JNZ       @
      CMP       DL,99H          ;  
      JBE       M2271
@:    OR        AH,1B           ; CF
      ADD       AL,60H          ; 

;----         ----

M2271:SAHF
      MOV       [RSP],AL
      POP       RAX,RDX
      RET
      
      



La base para cálculos precisos es la representación exacta de números en la memoria de la computadora. La representación BCD facilita la organización de cálculos precisos para números de cualquier longitud, es decir, cualquier precisión. Se ha demostrado en la práctica que para la mayoría de los cálculos económicos basta con una longitud de 15 decimales.





Literatura

1.D.R. Judd "Trabajar con archivos". Editorial "Mir" Moscú, 1975





2.http: //msdn.microsoft.com/ru-ru/library/system.decimal.aspx





3. D. Karavaev "Sobre la cuestión de mejorar el lenguaje de programación". Revista RSDN # 4 2011





4. L.F. Sternberg "Errores de programación y métodos de trabajo en el lenguaje PL / 1", Moscú "Ingeniería mecánica", 1993








All Articles