Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Simple program to find average of 3 numbers

0 views
Skip to first unread message

prashna

unread,
Jul 4, 2003, 1:01:18 AM7/4/03
to
Hi friends,

What is wrong in the following program which is giving constraint error?

procedure average is
type ONE_TO_100 is range 1 .. 100;

OBJ1,
OBJ2,
OBJ3,
AVG : ONE_TO_100;
begin
OBJ1 := 70;
OBJ2 := 70;
OBJ3 := 70;
AVG := OBJ1+OBJ2+OBJ3/3;
end average;


Thanks in advance

John R. Strohm

unread,
Jul 4, 2003, 1:22:27 AM7/4/03
to
"prashna" <vash...@rediffmail.com> wrote in message
news:d40d7104.0307...@posting.google.com...

> Hi friends,
>
> What is wrong in the following program which is giving constraint error?
>
> procedure average is
> type ONE_TO_100 is range 1 .. 100;
>
> OBJ1,
> OBJ2,
> OBJ3,
> AVG : ONE_TO_100;
> begin
> OBJ1 := 70;
> OBJ2 := 70;
> OBJ3 := 70;
> AVG := OBJ1+OBJ2+OBJ3/3;

-- This line doesn't do what you think it does.
-- Ask your TA to explain operator precedence to you in detail.

CephusŽ

unread,
Jul 4, 2003, 1:34:22 AM7/4/03
to

John R. Strohm wrote:
> "prashna" <vash...@rediffmail.com> wrote in message
> news:d40d7104.0307...@posting.google.com...
>> Hi friends,
>>
>> What is wrong in the following program which is giving constraint
>> error?
>>
>> procedure average is

>> SUBtype ONE_TO_100 is range 1 .. 100;


>>
>> OBJ1,
>> OBJ2,
>> OBJ3,
>> AVG : ONE_TO_100;
>> begin
>> OBJ1 := 70;
>> OBJ2 := 70;
>> OBJ3 := 70;

>> AVG := (OBJ1+OBJ2+OBJ3)/3;


>
> -- This line doesn't do what you think it does.
> -- Ask your TA to explain operator precedence to you in detail.
>
>> end average;
>>
>>
>> Thanks in advance

This is what it should be...


Beau


Robert I. Eachus

unread,
Jul 4, 2003, 1:33:58 AM7/4/03
to

I guess the right answer is that nothing is wrong with it, if you
want to be sure that you will get Constraint_Error. As written, the
code is required to raise Constraint_Error.

Oh, and then I could talk about your formatting, and identifier style.
But I will address those by example. Try:

procedure Average is
subtype One_to_100 is Integer range 1 .. 100;
Obj_1, Obj_2, Obj_3: One_to_100 := 70;
Avg: One_to_100;
begin
Avg := (Obj_1+Obj_2+Obj_3)/3;
-- I assume you really wanted the average, rather than 163.
end Average;

--

Robert I. Eachus

“In an ally, considerations of house, clan, planet, race are
insignificant beside two prime questions, which are: 1. Can he shoot? 2.
Will he aim at your enemy?” -- from the Laiden novels by Sharon Lee and
Steve Miller.

tmo...@acm.org

unread,
Jul 4, 2003, 1:39:38 AM7/4/03
to
>What is wrong in the following program which is giving constraint error?
70+70+70/3= 163 > 100
Have a restorative weekend. ;)

Stuart Palin

unread,
Jul 4, 2003, 4:37:45 AM7/4/03
to
"Robert I. Eachus" wrote:
>
> prashna wrote:
> > Hi friends,
> >
> > What is wrong in the following program which is giving constraint
> > error?
> >
> > procedure average is type ONE_TO_100 is range 1 .. 100;
> >
> > OBJ1, OBJ2, OBJ3, AVG : ONE_TO_100; begin OBJ1 := 70; OBJ2 := 70;
> > OBJ3 := 70; AVG := OBJ1+OBJ2+OBJ3/3; end average;
>
<snip>

>
> Oh, and then I could talk about your formatting, and identifier style.
> But I will address those by example. Try:
>
> procedure Average is
> subtype One_to_100 is Integer range 1 .. 100;
> Obj_1, Obj_2, Obj_3: One_to_100 := 70;
> Avg: One_to_100;
> begin
> Avg := (Obj_1+Obj_2+Obj_3)/3;
> -- I assume you really wanted the average, rather than 163.
> end Average;

You might also want to consider what values the intermediate
calculation Obj_1+Obj_2+Obj_3 can take. In this instance
because your type is constrained to a number which should be
well within the bounds of integer you would not experience a
problem.

Questions to ask yourself (and seek answers to):
a) What if the bounds of the type were larger?
b) How might it be possible to detect a potential constraint
error at compile time rather than during execution?

--
Stuart Palin

prashna

unread,
Jul 4, 2003, 5:28:25 AM7/4/03
to
tmo...@acm.org wrote in message news:<uq8Na.7195$NW6....@rwcrnsc51.ops.asp.att.net>...

> >What is wrong in the following program which is giving constraint error?
> 70+70+70/3= 163 > 100
> Have a restorative weekend. ;)

O.K, I have changed line 12 to AVG := (OBJ1+OBJ2+OBJ3)/3;
But still it giving constraint error!!! :((

Tarjei T. Jensen

unread,
Jul 4, 2003, 5:54:04 AM7/4/03
to
"Cephus®" wrote:
> This is what it should be...

He will not learn much if there is no effort in the learning.

You might think you have been helpful, but most likely you have done the
person a disservice.

greetings,


Stuart Palin

unread,
Jul 4, 2003, 7:02:54 AM7/4/03
to
prashna wrote:

> O.K, I have changed line 12 to AVG := (OBJ1+OBJ2+OBJ3)/3;
> But still it giving constraint error!!! :((

Having another look at your original posting, notice that
there is a difference between the way you have declared your
type and the way it is declared in Robert Eachus' example.

Do you get the exception with Robert's example?
If not what might be the underlying difference?

Think again about the points I raised earlier:

> You might also want to consider what values the intermediate
> calculation Obj_1+Obj_2+Obj_3 can take.

OK, the second sentence really applies to Robert's
example...


> In this instance because your type is constrained to a
> number which should be well within the bounds of integer
> you would not experience a problem.

What context might the expression be evaluated in in your
example?

(Think about 'base types' try ranges of 1..42 and 1..43
[with suitable initial values]. What interesting number
lies between 3*42 and 3*43?)

Pascal Obry

unread,
Jul 4, 2003, 12:20:49 PM7/4/03
to

vash...@rediffmail.com (prashna) writes:

> O.K, I have changed line 12 to AVG := (OBJ1+OBJ2+OBJ3)/3;
> But still it giving constraint error!!! :((

This is just not possible or it is a compiler bug (quite unlikely though). Be
sure to recompile and link your program.

Pascal.

--

--|------------------------------------------------------
--| Pascal Obry Team-Ada Member
--| 45, rue Gabriel Peri - 78114 Magny Les Hameaux FRANCE
--|------------------------------------------------------
--| http://perso.wanadoo.fr/pascal.obry
--| "The best way to travel is by means of imagination"
--|
--| gpg --keyserver wwwkeys.pgp.net --recv-key C1082595

Jeffrey Creem

unread,
Jul 4, 2003, 5:17:00 PM7/4/03
to
Remeber everyone. -gnato is your friend.


GNAT by default does not run with integer overflow checks enabled.

try again

gnatmake -f -gnato avg

Gets Constraint_Error on GNAT 3.15p under windows XP.

"Dennis Lee Bieber" <wlf...@ix.netcom.com> wrote in message
news:1e3ht-...@beastie.ix.netcom.com...
> prashna fed this fish to the penguins on Friday 04 July 2003 02:28 am:


>
> >
> > O.K, I have changed line 12 to AVG := (OBJ1+OBJ2+OBJ3)/3;
> > But still it giving constraint error!!! :((
>

> What compiler, and what OS?
>
>
> ---- avg.adb, using GNAT 3.15p, Mandrake Linux 8.2
>
> procedure avg is


>
> type ONE_TO_100 is range 1..100;
>

> Obj1, Obj2, Obj3 : ONE_TO_100;
> Avg : ONE_TO_100;
>
> begin
> Obj1 := 70;
> Obj2 := 70;
> Obj3 := 70;
>
> Avg := (Obj1 + Obj2 + Obj3) / 3;
> end avg;
>
> ----
> [wulfraed@beastie ada]$ gnatmake avg
> gcc -c avg.adb
> gnatbind -x avg.ali
> gnatlink avg.ali
>
> [wulfraed@beastie ada]$ ./avg
>
> No error (no output either, but you didn't have any shown...
>
> --
> > ============================================================== <
> > wlf...@ix.netcom.com | Wulfraed Dennis Lee Bieber KD6MOG <
> > wulf...@dm.net | Bestiaria Support Staff <
> > ============================================================== <
> > Bestiaria Home Page: http://www.beastie.dm.net/ <
> > Home Page: http://www.dm.net/~wulfraed/ <
>


Robert I. Eachus

unread,
Jul 4, 2003, 9:25:25 PM7/4/03
to
Pascal Obry wrote:
> vash...@rediffmail.com (prashna) writes:
>
>
>>O.K, I have changed line 12 to AVG := (OBJ1+OBJ2+OBJ3)/3;
>>But still it giving constraint error!!! :((
>
> This is just not possible or it is a compiler bug (quite unlikely though). Be
> sure to recompile and link your program.

Oh, no, it is very possible. It depend on the actual base type chosen
by the compiler. If that type is an 8-bit signed type, then since 210 >
127 you get Constraint_Error. That is why I changed the type
declaration to a subtype declaration in my rewrite.

Anders Wirzenius

unread,
Jul 5, 2003, 1:07:08 AM7/5/03
to

"Jeffrey Creem" <je...@thecreems.com> wrote in message
news:g9mNa.36436$926.3783@sccrnsc03...

> gnatmake -f -gnato avg
>
> Gets Constraint_Error on GNAT 3.15p under windows XP.

So the question arises: did the OP specify -gnato? If no, there might
be something wrong with his compiler :-)

Anders

Preben Randhol

unread,
Jul 5, 2003, 6:06:07 AM7/5/03
to

Which instance are you refering to? Mr Eachus' subtype or OP's type
declaration? If you do the calculations above aren't the
intermediate variable of the same type (ONE_TO_100) with same contraint
unless you use a subtype to Integer like Mr Eachus?

--
Ada95 is good for you.
http://www.crystalcode.com/codemage/MainMenu/Coding/Ada/IntroducingAda.php

Marqmc5

unread,
Jul 5, 2003, 10:39:59 AM7/5/03
to
The sum of OBJ1 + OBJ2 +OBJ3 is 210, which is a bit over 100, out of range of
your type-cast.

CephusŽ

unread,
Jul 5, 2003, 1:49:00 PM7/5/03
to

well if he can't see that then he/she really won't be hurt by my help...
THAT IS SOMETHING IN ALGEBRA YOU LEARN IN ELEMENTARY! he just probably
forgot that.... geezzz...

Beau


g_ak

unread,
Jul 5, 2003, 11:47:09 PM7/5/03
to


prashna,

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

prashna

unread,
Jul 8, 2003, 1:06:28 AM7/8/03
to
> 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;)?

Thanks

Matthew Heaney

unread,
Jul 9, 2003, 11:25:44 AM7/9/03
to
vash...@rediffmail.com (prashna) wrote in message news:<d40d7104.03070...@posting.google.com>...

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.

Robert I. Eachus

unread,
Jul 9, 2003, 5:38:43 PM7/9/03
to
Matthew Heaney wrote:

> 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.

AT LEAST all the values in the range, and is symmetric around zero with
a possible extra negative value. (Can you tell I am a language lawyer
by nature?)

If you want to ensure a precise range for the base type, specify the
size as well:

type Tiny_Int is range -128..127;
for Tiny_Int'Size use 8;

> The addition is computed using the range of values in the base type.

No, "The predefined operations on integer types either yield the
mathematically correct result or raise the exception Constraint_Error."
RM 4.5(10) Arithmetic operations are not required to raise
Constraint_Error if the value of the expression as a whole is in range,
because that would prevent many useful optimizations. (However, the
sentence above was moved from 11.6 in Ada 83 to 4.5. But the meaning
hasn't changed.) For example, if you write Z := 2*X + 2*Y; the compiler
is allowed to generate code for 2*(X+Y). This will only generate an
exception in cases where 2*X + 2*Y does, but there are some cases where
you get the correct mathmatical result with the optimized expression,
and a Constraint_Error with the unoptimized version.

> 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...

Correct.

> 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.

It corresponds to:

subtype T is <implementation defined integer type> range 1..100;

except that one thing we learned from Ada 83 is that such "helpful"
analogies are always wrong. ;-) Which is why you won't find any in the
Ada 95 RM.

If you want to find out what the compiler will do you can write a short
program to find out:
--------------------------------------------------------------------------
with Ada.Text_IO; use Ada.Text_IO;
procedure Num_Types is

type One_To_100 is range 1..100;

type Eight_Bits is range 1..100;
for Eight_Bits'Size use 8;

begin

New_Line;
Put_Line(" Type One_To_100 is " &
Integer'Image(Integer(One_To_100'Base'First))
& ".." & Integer'Image(Integer(One_To_100'Base'Last)) & '.');
Put_Line(" Type Eight_Bits is " &
Integer'Image(Integer(Eight_Bits'Base'First))
& ".." & Integer'Image(Integer(Eight_Bits'Base'Last)) & '.');
New_Line;

end Num_Types;
------------------------------------------------------------------------
with GNAT:

num_types

Type One_To_100 is -128.. 127.
Type Eight_Bits is -128.. 127.

If I seem to be picking on Matt, I'm not. His answer was close enough
to right that I wanted to be sure to correct the spots where it wasn't
perfect. This is an area where the changes in the rules between Ada 83
and Ada 95 can be confusing, even though for the most part they say
exactly the same thing. (The differences are very subtle, involving
what you can count on being correct after Constraint_Error is raised.)

Simon Wright

unread,
Jul 10, 2003, 12:55:05 AM7/10/03
to
mhe...@on2.com (Matthew Heaney) writes:

> 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.)

I think the overflow checks are for overflow in the base type, so for
T_Base is new Integer you'ld have to do something like Integer'Last +
1.

Matthew Heaney

unread,
Jul 10, 2003, 9:52:40 AM7/10/03
to
"Robert I. Eachus" <riea...@attbi.com> wrote in message news:<3F0C8B45...@attbi.com>...

> Matthew Heaney wrote:
>
> > 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.
>
> It corresponds to:
>
> subtype T is <implementation defined integer type> range 1..100;
>
> except that one thing we learned from Ada 83 is that such "helpful"
> analogies are always wrong. ;-) Which is why you won't find any in the
> Ada 95 RM.

But the question is: what is the base range of the "implementation
defined integer type"? For declarations of this style:

type T is new Integer range 1 .. 100;

can was assume that the base range of the type includes all the values
in Integer'Base, or only the values in the range -100 .. 100?

With respect to the base range of the type, how do the declarations

type T is new Integer range 1 .. 100;

type T is range 1 .. 100;

differ from one another?

Robert I. Eachus

unread,
Jul 10, 2003, 11:46:00 AM7/10/03
to
Matthew Heaney wrote:

> But the question is: what is the base range of the "implementation
> defined integer type"? For declarations of this style:
>
> type T is new Integer range 1 .. 100;
>
> can was assume that the base range of the type includes all the values
> in Integer'Base, or only the values in the range -100 .. 100?

In that case T'Base has the same range as Integer'Base.

> With respect to the base range of the type, how do the declarations
>
> type T is new Integer range 1 .. 100;
> type T is range 1 .. 100;
>
> differ from one another?

Look at the output from the program I provided. In the first case, the
base type has the same characteristics as Integer'Base. In the second
example, look at the results of the program I ran. The compiler can
choose any predefined integer type for the base type. In this case,
GNAT choose one with a range -128..127.

Randy Brukardt

unread,
Jul 10, 2003, 8:56:36 PM7/10/03
to
> Matthew Heaney wrote:
> > With respect to the base range of the type, how do the declarations
> >
> > type T is new Integer range 1 .. 100;
> > type T is range 1 .. 100;
> >
> > differ from one another?

For the first, the base type is derived from Integer'Base. So T'Base'First =
Integer'Base'First.

OTOH, all we know about the second T is that T'First <= -100, and T'Last >=
100. (Generally, it is some power of two). Thus, the second gives more power
to the compiler, and thus is preferred.

For instance, Janus/Ada has historically used Integer'Size = 16 (that kept
all of our compilers compatible -- probably a bad choice, but it is
impossible to change without breaking a lot of user code).
type T1 is Integer range 0 .. 100_000;
-- Raises Constraint_Error on most versions of Janus/Ada; will work
on GNAT, etc.
type T2 is range 0 .. 100_000;
-- Works fine on all modern versions of Janus/Ada.

Randy.

Robert A Duff

unread,
Jul 11, 2003, 5:50:39 PM7/11/03
to
"Robert I. Eachus" <riea...@attbi.com> writes:

> If you want to ensure a precise range for the base type, specify the
> size as well:
>
> type Tiny_Int is range -128..127;
> for Tiny_Int'Size use 8;

The Size clause has no effect on the base range.

- Bob

Robert A Duff

unread,
Jul 11, 2003, 5:54:56 PM7/11/03
to
mhe...@on2.com (Matthew Heaney) writes:

> But the question is: what is the base range of the "implementation
> defined integer type"? For declarations of this style:
>
> type T is new Integer range 1 .. 100;
>
> can was assume that the base range of the type includes all the values
> in Integer'Base,

Yes.

>... or only the values in the range -100 .. 100?


>
> With respect to the base range of the type, how do the declarations
>
> type T is new Integer range 1 .. 100;

Base range is at least Integer'First..Integer'Last,
which is at least the 16-bit range.

> type T is range 1 .. 100;

Base range is at least -100..100.

> differ from one another?

The above is according to the RM. These are minimal ranges. Compilers
can choose wider base ranges, and for any particular expression, the
compiler is always allowed to get the right answer even if it is outside
the base range. Base ranges give you a minimal range for intermediate
results, guaranteed not to overflow.

- Bob

Robert I. Eachus

unread,
Jul 11, 2003, 7:32:36 PM7/11/03
to
Robert A Duff wrote:

> The Size clause has no effect on the base range.

From a language lawyer point of view, I guess that is true, just not
all that helpful. In Ada 83 some compilers did allow a 'Size clause to
influence representations. It was the easiest way to deal with the
"junk" for Character'Size use 7; in (Ada 83) package Standard. And as
long as you were dealing with that to pass the ACVC tests, might as well
actually try to do something useful with it. Of course, on the
compilers that cared, very few implemented all the possible integer base
types. (Ada/SIL did support Integer_2 through Integer_16 plus (32-bit)
Long_Integer as potential base types, but would choose Integer (16-bits)
for all smaller types absent a size clause.

0 new messages