Project

General

Profile

Actions

Defect #673

open

Real procedure in obl.out.mod overflows for large values

Added by Runar Tenfjord about 1 year ago.

Status:
New
Priority:
Normal
Category:
Oberon Library
Target version:
-
% Done:

0%


Description

If the whole part of REAL value is larger than what can fit in LONGINT
the procedure fails.

I have ported some code from Modula-2 which implements this functionality
which may be an inspiration solve this issue.

This is still very simple, but seems to work OK and is probably good enough
for debug printing.

MODULE Test;

CONST
    MaxRoundArray   = 17;

VAR
    RoundValue : ARRAY MaxRoundArray OF REAL;

PROCEDURE FormatFix(VAR str : ARRAY OF CHAR; value : REAL; prec: INTEGER);
VAR
    i, digits, round, val : INTEGER;
BEGIN
    IF (prec <= 0) OR (prec > 17) THEN prec := 17 END;
    IF value < 0 THEN
        value := ABS(value);
        ArrayOfChar.AppendChar(str, '-'); 
    END;
    (* force real to less than 10 *)
    round := prec;
    digits := 1;
    WHILE value >= 10.0 DO
        IF value >= 1.0E4 THEN
            value := value / 1.0E4;
            INC(digits, 4);
        ELSIF value >= 1.0E2 THEN
            value := value / 1.0E2;
            INC(digits, 2);
        ELSE
            value := value / 10.0;
            INC(digits, 1);
        END;
    END;
    (* round off *)
    round := prec + (digits - 1);
    IF round < 0 THEN
        round := 0
    ELSIF round > MaxRoundArray - 1 THEN
        round := MaxRoundArray - 1;
    END;
    value := value + RoundValue[round];
    IF value >= 10.0 THEN
        value := value / 10.0;
        INC(digits);
    END;
    (* write digits *)
    FOR i := 1 TO digits DO
        val := ENTIER(value);
        ArrayOfChar.AppendChar(str, CHR(ORD('0') + val MOD 10)); 
        value := 10*(value - val);
    END;
    (* write fractional part *)
    IF prec >= 0 THEN
        ArrayOfChar.AppendChar(str, '.');
        INC(prec, digits);
        WHILE digits < prec DO
            val := ENTIER(value);
            ArrayOfChar.AppendChar(str, CHR(ORD('0') + val MOD 10)); 
            value := 10*(value - val);
            INC(digits);
        END;
    END;
END FormatFix;

BEGIN
    RoundValue[0] := 0.5; RoundValue[1] := 5.0E-2;
    RoundValue[2] := 5.0E-3; RoundValue[3] := 5.0E-4;
    RoundValue[4] := 5.0E-5; RoundValue[5] := 5.0E-6;
    RoundValue[6] := 5.0E-7; RoundValue[7] := 5.0E-8;
    RoundValue[8] := 5.0E-9; RoundValue[9] := 5.0E-10;
    RoundValue[10] := 5.0E-11; RoundValue[11] := 5.0E-12;
    RoundValue[12] := 5.0E-13; RoundValue[13] := 5.0E-14;
    RoundValue[14] := 5.0E-15; RoundValue[15] := 5.0E-16;
    RoundValue[16] := 5.0E-17;
END Test.

No data to display

Actions

Also available in: Atom PDF