comp.lang.ada
 help / color / mirror / Atom feed
From: mheaney@on2.com (Matthew Heaney)
Subject: Re: Simple program to find average of 3 numbers
Date: 9 Jul 2003 08:25:44 -0700
Date: 2003-07-09T15:25:45+00:00	[thread overview]
Message-ID: <1ec946d1.0307090725.73f5f200@posting.google.com> (raw)
In-Reply-To: d40d7104.0307072106.1ad3b378@posting.google.com

vashwath@rediffmail.com (prashna) wrote in message news:<d40d7104.0307072106.1ad3b378@posting.google.com>...
> > you shoud declare your type "one_to_100" differently... 
> > this should work better:
> > -------------------------------------------------------
> > procedure Average is
> > 
> >     type One_To_100 is new Integer range 1 .. 100;
> > 
> >     Obj1,
> >     Obj2,
> >     Obj3,
> >     Avg  : One_To_100;
> > 
> > begin
> >     Obj1 := 70;
> >     Obj2 := 70;
> >     Obj3 := 70;
> >     AVG := (OBJ1+OBJ2+OBJ3)/3;
> > end Average;
> > 
> > -------------------------------------------------------
> > 
> > you will get a constraint error only when the sum of OBJ1+OBJ2+OBJ3 will
> > reach a number higher than the highest permited  value in the Integer 
> > type (2**15-1 if iremember well)
> > 
> > gilles
> 
> 
> Thanks every one for the replies.
> 
> Among these two type declarations which is better one?In my opinion
> declaring a type as derived type of another type (integer in this
> case) is better one because the intermediate results of arithmetic
> operations will be stored as integer type or Is there any advantage of
> declaring a type as just a values within certain range (ex:type
> ONE_TO_100 is range 1 .. 100;)?

This is actually an important question, because it highlights some
subtleties in the Ada type system.

In the type declaration

  type T is range 1 .. 100;

the type T is actually a subtype of the underlying type.  The
underlying type has no name, but we can refer to it as T'Base.  The
name T is its "first named subtype."

The type has a range that includes all the values in the first named
subtype T, and is symmetric around 0.

So what we really have is this:

  type T'Base is range -100 .. 100;
  subtype T is T_Base range 1 .. 100;

The predefined operations for an integer type are declared this way:

  function "+" (L, R : T'Base) return T'Base;

Note that the types in the function declaration are T'Base, not T.  

The addition is computed using the range of values in the base type. 
In particular, this means that the programmer is responsible for
ensuring that the base range of the type includes a wide enough range
to compute intermediate values during expression evalution.

The intermediate sum in your example has a value 3 * 70 = 210, which
is outside the base range of the type, which only includes values up
to 100.

This means that your type declaration is wrong.  The intermediate
value causes integer overflow, because the value is outside the base
range of the type.

What you need to do is declare your type this way:

declare
   type T_Base is range -300 .. 300;
   subtype T is T_Base range 1 .. 100;

   X, Y, Z : constant T := 70;
   Sum : constant T := (X + Y + Z) / 3;
begin

The executes fine using gnat 3.15p on WinXP.

The moral of the story is that you have to you have to take
responsibility for ensuring that you have a type that is large enough
for intermediate values.  So must analyze your algorithm to determine
what the max value is.

You can simplify things by declaring your base type as deriving from
type Integer:

declare
  type T_Base is new Integer;
  subtype T is T_Base range 1 .. 100;
...
begin

This gives you a range that is "natural" for your machine.  However,
it's still up to you to perform a minimal boundary analysis of your
algorithm to ensure that intermediate values can be safely computed. 
This is true when programming in any language.  The difference when
programming in Ada is that Ada lets you know when you made a mistake.

As was pointed out, when using gnat you should always specify the
-gnato option, to enable integer overflow checks.  (However, I did get
the overflow check without specifying that switch, so perhaps
something has changed in the 3.15p release of gnat.)

The type declaration in your example looks like this:

  type T is new Integer range 1 .. 100;

However, I'm not sure whether it corresponds to the declarations

  type T_Base is new Integer;
  subtype T is T_Base range 1 .. 100;

or to the declarations:
 
   type T_Base is range -100 .. 100;
   subtype T is T_Base range 1 .. 100;

It executes fine when I run it, so it seems to correspond to the
former pair.



  reply	other threads:[~2003-07-09 15:25 UTC|newest]

Thread overview: 28+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2003-07-04  5:01 Simple program to find average of 3 numbers prashna
2003-07-04  5:22 ` John R. Strohm
2003-07-04  5:34   ` Cephus�
2003-07-04  9:54     ` Tarjei T. Jensen
2003-07-05 17:49       ` Cephus�
2003-07-04  5:33 ` Robert I. Eachus
2003-07-04  8:37   ` Stuart Palin
2003-07-05 10:06     ` Preben Randhol
2003-07-04  5:39 ` tmoran
2003-07-04  9:28   ` prashna
2003-07-04 11:02     ` Stuart Palin
2003-07-04 16:20     ` Pascal Obry
2003-07-05  1:25       ` Robert I. Eachus
     [not found]     ` <1e3ht-ig4.ln1@beastie.ix.netcom.com>
2003-07-04 21:17       ` Jeffrey Creem
2003-07-05  5:07         ` Anders Wirzenius
2003-07-05 14:39 ` Marqmc5
2003-07-06  3:47 ` g_ak
2003-07-08  5:06   ` prashna
2003-07-09 15:25     ` Matthew Heaney [this message]
2003-07-09 21:38       ` Robert I. Eachus
2003-07-10 13:52         ` Matthew Heaney
2003-07-10 15:46           ` Robert I. Eachus
2003-07-11  0:56             ` Randy Brukardt
2003-07-11 21:54           ` Robert A Duff
2003-07-11 21:50         ` Robert A Duff
2003-07-11 23:32           ` Robert I. Eachus
2003-07-10  4:55       ` Simon Wright
  -- strict thread matches above, loose matches on Subject: below --
2003-07-09  6:24 christoph.grein
replies disabled

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