comp.lang.ada
 help / color / mirror / Atom feed
From: aratel@total.net (Andre Ratel)
Subject: Re: Ada vs Delphi?
Date: 1999/08/14
Date: 1999-08-14T00:00:00+00:00	[thread overview]
Message-ID: <37b54516.54588055@news.total.net> (raw)
In-Reply-To: 37B27FE8.6E09569E@Maths.UniNe.CH

My post is a bit long. I apologize, but I really want to get to the
bottom of this.

-=[Knowing the range]=----------

On Thu, 12 Aug 1999 10:03:52 +0200, Gautier
<Gautier.deMontmollin@Maths.UniNe.CH> wrote:

>Neither Delphi nor you can guess if the result of an expression
>like (n1 + n2) alone will be in some range. 

It depends. More often than not, I use integers as counters.
For example, let's consider an hypothetical situation in which 
we have the following loop

<<<
  for n1:= -128 to 127
    for n2:= -128 to 127
      begin
        sum:= n1 + n2;
        ...
      end; {for}
>>>

We know the ranges of n1 and n2 and we have a pretty good idea
of the range of sum. Now, how do we declare these variables?
One way to do it, is to put all related variables in a same
set, chosen large enough to contain all their possible 
values:

  var
    n1, n2, sum: integer;

The other would be to use smaller sets:

  var
    n1, n2: -128..127; {or equivalently: n1, n2: shorting;}
    sum: integer;

With the latter declarations, we won't run into trouble if:
  - the right-side of the expression is evaluated using the
    largest set of integers (longint)
  - the result is typecasted into the variable on the left-side
  - some kind of error message pops up if one of the variable
    gets outside its declared range.

When I began programming in Turbo Pascal, I tended to follow 
this second approach but ran into all sorts of problems. Now,
apart from a few exceptional cases, I use integers or longints.

A safe language should be such that all evaluations are performed
using the largest set of numerals available (longint for integers,
extended for real numbers). The responsability of the programmer
would be then to choose the appropriate type of variables for 
_storing_ the results in memory. (I am aware that this might lead 
to problems in efficiency.)

Let's see if Turbo Pascal satisfies this safety requirement.


-=[Calculating with floating point]=----------

From the Turbo Pascal (v. 5) Reference Guide (pp. 185-186):

<<<
The extended type is the basis of all floating-point computations
with the 8087. Turbo Pascal uses the extended format to store
all non-integer numeric expressions using extended precision.
The entire right-side of the following assignment, for instance,
will be computed in extended before being converted to the type
on the left side:

  {$N+} {using the numerical coprocessor}
  
  var
    X, A, B, C: real;
  begin
    X:= (B + Sqrt(B*B - A*C))/A;
  end;

With no special effort by the programmer, Turbo Pascal performs
computations using the precision and range of the extended type.
The added precision means smaller round-off errors, and the
additional range means overflow and underflow are less common.
>>>

So, for floating points, everything seems safe enough.


-=[Calculating with integers]=----------

From the Reference Guide p. 26:

<<<
  * The type with an integer constant is the predefined 
    integer with the smallest range that includes the value
    of the integer constant.
  * For all binary operators (an operator that takes two
    operands), both operands are converted to their common
    type before the operation. The _common_type_ is the 
    predefined integer type with the the smallest range that
    includes all possible values of both types. For instance,
    the common type of integer and byte is integer, and the
    common type of integer and word is longint. The operation
    is performed using the precision of the common type, and
    the result type is the common type.
  * The expresssion on the right of an assignment is evaluated
    independently from the size or the type of the variable on
    the left.
  * Any byte sized operand is converted to an intermediate 
    word-sized type operand that is compatible with both 
    integer and word before any arithmetic operation is
    performed.
>>>

So the problems of Turbo Pascal with integers arise from the
fact that, for the evaluation of expressions, the common type
is used instead of the largest set available (longint).


-=[Your example]=----------

I can now better understand the example you gave me.

<<<
{$R+}

  var
    n1, n2: shortint; {range: -128 .. 127}
    i1,i2:  integer;  {range: -32768..32767}
    N: longint; {range: -2147483648 .. 2147483647}

  begin
    n1:= 120;
    n2:= 120;
    N:= n1 + n2;
    Writeln(N);

    i1:= 32000;
    i2:= 32000;
    N:= i1 + i2;
    Writeln(N);
  end.
>>>

Since n1 and n2 are byte-sized, they are both converted to
word-sized and this is why, for (n1 + n2), we get the correct
result 240.

For (i1 + i2), the common type (integer) is used for the 
evaluation and, since the sum is outside the range, we get
the wrong result -1536. This problem could be avoided if,
instead of using the common type, Turbo Pascal would use
longint.

I tried your example with Turbo Pascal 5 (I admit, at first,
I didn't believe the results and tought there was some
error in the listing). I also tried some variations on it.
First, I replaced the n1, n2, i1, and i2 declarations by

    n1, n2: -128..127;
    i1, i2: -32768..32767;

and, not surprisingly, got the same results (240 and -1536).

Now, what would happen if I declare i1 and i2 as constants:

<<<
{$R+}

  const
    i1 = 32000;
    i2 = 32000;
    
  var
    n1, n2: shortint; {range: -128 .. 127}
    N: longint; {range: -2147483648 .. 2147483647}

  begin
    n1:= 120;
    n2:= 120;
    N:= n1 + n2;
    Writeln(N);

    N:= i1 + i2;
    Writeln(N);
    N:= i1 - 5*i2; {here, I put something new}
    Writeln(N);
  end.
>>>

According to the first rule above, i1 and i2 should each be 
casted as "integer with the smallest range that includes the
value of the integer constant". Since integer is the smallest 
range including 32000, we should again get into trouble.
Surprisingly, when I run the above program, I get the correct
results:
  240
  64000
  -128000
So, it seems, something is still escaping me. (On the other hand,
I'm glad that, here, we get the correct answers. Otherwise, using
constants would turn into a programming nightmare.)


-=[Handling types with Ada]=----------

Getting back to my first example:

<<<
  for n1:= -128 to 127
    for n2:= -128 to 127
      begin
        sum:= n1 + n2;
        ...
      end; {for}
>>>

how would you declare variables n1, n2, and sum in Ada?

> In Ada you can handle ranges and bits independently:
> e.g. a 32-bit subtype of range -127..128, etc. etc.
> In the same subtype family (e.g. integer, natural, positive)
> you can write n1+n2 safely, without explicit conversion, as
> there is no bad surprise with hidden type conversions; ranges
> will be checked correctly - provided you didn't suppress them
> at compile time...

This is new to me. I've never seen something like this in the
languages I used before (Fortran 77, Pascal, C, IDL). I think
I'm beginning to get the idea but I would appreciate a small
example of this, just to see how this looks like in Ada.

	Andre

PS: Thanks to all those who participate in this exchange. I really
    appreciate the input.





  reply	other threads:[~1999-08-14  0:00 UTC|newest]

Thread overview: 49+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
1999-08-06  0:00 Ada vs Delphi? Andre Ratel
1999-08-06  0:00 ` Steve Doiel
1999-08-09  0:00   ` Paul Groves
1999-08-08  0:00     ` Steve Doiel
1999-08-10  0:00       ` Ray Blaak
1999-08-10  0:00         ` Steve Doiel
1999-08-14  0:00           ` Andre Ratel
1999-08-09  0:00     ` Robert Dewar
1999-08-11  0:00       ` Andre Ratel
1999-08-11  0:00         ` Ted Dennison
1999-08-14  0:00           ` Andre Ratel
1999-08-16  0:00             ` Ted Dennison
1999-08-11  0:00         ` Robert Dewar
1999-08-14  0:00           ` Andre Ratel
1999-08-17  0:00             ` Robert I. Eachus
1999-08-11  0:00         ` Robert Dewar
1999-08-11  0:00           ` David Botton
1999-08-14  0:00           ` Andre Ratel
1999-08-09  0:00     ` Aidan Skinner
1999-08-09  0:00     ` Robert Dewar
1999-08-09  0:00     ` Gautier
1999-08-11  0:00       ` Andre Ratel
1999-08-12  0:00         ` Gautier
1999-08-12  0:00         ` Gautier
1999-08-14  0:00           ` Andre Ratel [this message]
1999-08-14  0:00             ` Gautier
1999-08-16  0:00               ` Gautier
1999-08-15  0:00             ` Steve Doiel
1999-08-17  0:00             ` Robert I. Eachus
1999-08-10  0:00     ` Brian Rogoff
1999-08-11  0:00       ` Scientific calculations (was Re: Ada vs Delphi? ) Vladimir Olensky
1999-08-11  0:00         ` Robert Dewar
1999-08-11  0:00         ` Robert Dewar
1999-08-11  0:00           ` Vladimir Olensky
1999-08-13  0:00             ` Robert Dewar
1999-08-13  0:00               ` Brian Rogoff
1999-08-15  0:00               ` Vladimir Olensky
1999-08-15  0:00                 ` Vladimir Olensky
1999-08-13  0:00             ` Gautier
1999-08-11  0:00     ` Ada vs Delphi? Andre Ratel
1999-08-11  0:00       ` Ada vs Component Pascal (was: Ada vs Delphi?) Ted Dennison
1999-08-11  0:00       ` Ada vs Delphi? Robert Dewar
1999-08-14  0:00         ` Andre Ratel
1999-08-06  0:00 ` William Starner
1999-08-06  0:00   ` William Starner
1999-08-07  0:00   ` tmoran
1999-08-07  0:00     ` Aidan Skinner
1999-08-07  0:00       ` Gautier
1999-08-07  0:00 ` Gautier
replies disabled

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox