Binary coded decimal: Difference between revisions
Content added Content deleted
(Added Algol 68) |
(Added Algol W) |
||
Line 183: | Line 183: | ||
33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 |
33 32 31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 |
||
12 11 10 09 08 07 06 05 04 03 02 01 00 -01 -02 -03 -04 -05 -06 -07 -08 |
12 11 10 09 08 07 06 05 04 03 02 01 00 -01 -02 -03 -04 -05 -06 -07 -08 |
||
</pre> |
|||
=={{header|ALGOL W}}== |
|||
{{Trans|ALGOL 68}} |
|||
<lang algolw>begin % implements BCD arithmetic for 2-digit signed packed BCD % |
|||
integer X99; % maximum unsigned BCD value % |
|||
% structure to hold BCD values % |
|||
record BCD ( integer dValue % signed BCD value: -x99 to x99 % |
|||
; logical dCarry % TRUE if the value overflowed, % |
|||
); % FALSE otherwise % |
|||
% constructs a BCD value from a, assuming it is in the correct format % |
|||
% if the value has overflowed, it is truncated to a valid value and % |
|||
% carry is set % |
|||
reference(BCD) procedure asBcd ( integer value a ) ; |
|||
begin |
|||
integer v; |
|||
logical carry; |
|||
v := abs a; |
|||
carry := v > X99; |
|||
if carry then v := ( ( ( v div 16 ) rem 10 ) * 16 ) + ( v rem 16 ); |
|||
BCD( if a < 0 then - v else v, carry ) |
|||
end asBcd ; |
|||
% returns a converted to BCD format, truncating and setting carry % |
|||
% if necessary % |
|||
reference(BCD) procedure toBcd ( integer value a ) ; |
|||
if a < 0 |
|||
then negateBcd( toBcd( abs a ) ) |
|||
else BCD( ( ( ( a div 10 ) rem 10 ) * 16 ) + ( a rem 10 ), a > X99 ) |
|||
; |
|||
% returns the value of b negated, carry is preserved % |
|||
reference(BCD) procedure negateBcd ( reference(BCD) value a ) ; BCD( - dValue(a), dCarry(a) ); |
|||
% writes a two-digit string representation of the BCD value a % |
|||
procedure writeOnBcd ( reference(BCD) value a ) ; |
|||
begin |
|||
if dValue(a) < 0 then writeon( s_w := 0, "-" ); |
|||
writeon( i_w := 1, s_w := 0 |
|||
, abs dValue(a) div 16 |
|||
, abs dValue(a) rem 16 |
|||
) |
|||
end writeOnBcd; |
|||
% writes a BCD value with a preceeding newline % |
|||
procedure writeBcd ( reference(BCD) value a ) ; begin write(); writeOnBcd( a ) end; |
|||
% returns the sum of a and b, a and b can be positive or negative % |
|||
reference(BCD) procedure addBcd ( reference(BCD) value a, b ) ; |
|||
begin |
|||
integer av, bv, a2, b2, bcdResult; |
|||
logical ap, bp; |
|||
av := abs dValue(a); bv := abs dValue(b); |
|||
ap := dValue(a) >= 0; bp := dValue(b) >= 0; |
|||
a2 := av rem 16; b2 := bv rem 16; |
|||
if ap = bp then begin |
|||
bcdResult := av + bv; |
|||
if a2 + b2 > 9 then bcdResult := bcdResult + 6; |
|||
if not ap then bcdResult := - bcdResult |
|||
end |
|||
else if av >= bv then begin |
|||
bcdResult := av - bv; |
|||
if a2 < b2 then bcdResult := bcdResult - 6; |
|||
if not ap then bcdResult := - bcdResult |
|||
end |
|||
else begin |
|||
bcdResult := bv - av; |
|||
if b2 < a2 then bcdResult := bcdResult - 6; |
|||
if ap then bcdResult := - bcdResult |
|||
end if_ap_eq_bp__av_ge_bv__; |
|||
asBcd( bcdResult ) |
|||
end addBcd; |
|||
% returns the difference of a and b, a and b can be positive or negative % |
|||
reference(BCD) procedure subtractBcd ( reference(BCD) value a, b ) ; addBcd( a, negateBcd( b ) ); |
|||
X99 := ( 9 * 16 ) + 9; |
|||
begin % task test cases % |
|||
reference(BCD) r; |
|||
writeBcd( addBcd( toBcd( 19 ), toBcd( 1 ) ) ); |
|||
writeBcd( subtractBcd( toBcd( 30 ), toBcd( 1 ) ) ); |
|||
r := addBcd( toBcd( 99 ), toBcd( 1 ) ); |
|||
if dCarry(r) then write( s_w := 0, "1" ); |
|||
writeOnBcd( r ); |
|||
end |
|||
end.</lang> |
|||
{{out}} |
|||
<pre> |
|||
20 |
|||
29 |
|||
100 |
|||
</pre> |
</pre> |
||