comp.lang.ada
 help / color / mirror / Atom feed
* Re: fixed type (delta) in ada
  1999-11-27  0:00 fixed type (delta) in ada Nap
@ 1999-11-26  0:00 ` Al Christians
  1999-11-27  0:00   ` fixed type (delta) in ada and GNAT bug David C. Hoos, Sr.
  1999-11-28  0:00 ` fixed type (delta) in ada Nick Roberts
  1999-11-28  0:00 ` Robert Dewar
  2 siblings, 1 reply; 17+ messages in thread
From: Al Christians @ 1999-11-26  0:00 UTC (permalink / raw)


I ran your test with GNAT 3.12p under Windows NT on Pentium Pro.  I 
get the answer = 68.55.  Equally no good or even a little worse.

Your fixed point numbers are all binary fixed point.  This is all 
according to the book; don't worry.

Delta = 0.01 works out to use binary fixed point with 7 bits to the 
right of the binary point, ie numbers are represented as some number 
of 128ths; 1/128 is less than 0.01, so these are good to 2 decimal 
digits to the right of the decimal point.  Unfortunately, it looks 
like your 0.20 value gets represented by GNAT as 25/128, even though  
26/128 is a little closer, neither is very close.  Whatever Ada you 
were using is using 26/128 and is a little more accurate than GNAT 
3.12p, but there's a way around this either way (below).

If I do this:
 
a:     constant := 351.0;
b:     constant := 1.0/5.0;
d:     constant := a * b;
c:     constant money := d;

Then c comes out with the right value of 70.2.  a, b, and
d, are each of type universal_real, with beaucoups of significant
digits, and therefore c comes out ok.


But if I do this:
 
a:     constant := 351.0;
b:     constant := 1.0/5.0;
c:     constant money := a * b;

Then c still comes out 68.55.  Looks like the a and b get converted
to the money type before they get multiplied.  Ouch.

But to make money a decimal fixed point type type, do this:

-----------------------------------------------------------

with Ada.Text_IO;

procedure Money_Test is

type money is delta 0.01 digits 10 range 0.0..10_000_000.00;

a:     money;
b:     money;
c:     money;

package money_io is new ada.text_io.decimal_io(money);


begin
a     := 351.0;
b     := 0.20;
c     := (a * b);   
money_io.put(c);  -- Prints 70.2 
end Money_Test;

--------------------------------------------------------------

This gives the right answer with no error.  The range constraint
on the money type is optional; the digits + delta part combined
make the numbers act like decimal numbers.



Al


Nap wrote:
> 
> does anyone know why mutiplication between fixed type in ada produce a
> big round off error?
> 
> type money is delta 0.01 range 0.0..100_000_000.00;
> a, b, c : money;
> 
> package money_io is new ada.text_io.fixed_io(money);
> 
> a := 351.00;
> b := 0.20;
> c := a * b;
> 
> money_io.put(c);
> 
> -- the output should be 70.2 but it prints 71.3 instead.
> -- this is so frustrating. typecasting (back to float) doesn't help
> either.
> 
> Thanks,
> Nap




^ permalink raw reply	[flat|nested] 17+ messages in thread

* fixed type (delta) in ada
@ 1999-11-27  0:00 Nap
  1999-11-26  0:00 ` Al Christians
                   ` (2 more replies)
  0 siblings, 3 replies; 17+ messages in thread
From: Nap @ 1999-11-27  0:00 UTC (permalink / raw)


does anyone know why mutiplication between fixed type in ada produce a
big round off error?

type money is delta 0.01 range 0.0..100_000_000.00;
a, b, c : money;

package money_io is new ada.text_io.fixed_io(money);

a := 351.00;
b := 0.20;
c := a * b;

money_io.put(c);

-- the output should be 70.2 but it prints 71.3 instead.
-- this is so frustrating. typecasting (back to float) doesn't help
either. 

Thanks,
Nap




^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: fixed type (delta) in ada and GNAT bug
  1999-11-26  0:00 ` Al Christians
@ 1999-11-27  0:00   ` David C. Hoos, Sr.
  0 siblings, 0 replies; 17+ messages in thread
From: David C. Hoos, Sr. @ 1999-11-27  0:00 UTC (permalink / raw)


The reason "why mutiplication between fixed type in ada produce a
big round off error," is that the language standard specifies the
'Small attribute of an "ordinary_fixed_point_definition" to be a
[integer] power of 2 (RM95 3.5.9 (8).

However, from a mathematical point of view, the multiplication of
a money value by a money value is nonsense.  It only makes sense to
multiply (or divide) money values by dimensionless quantities, such
as the number of items purchased, or an interest rate.  These
quantities should be expressed in the programming language by some
type other than a money type.

There are two ways of specifying the 'Small attribute to be an
integer power of 10 -- specify the 'Small attribute directly with
an attribute_definition_clause (this method is not restricted to
integer powers of 10 -- any desired value equal to or less than
the delta is allowed), or define the type with s
decimal_fixed_point_definition -- see RM95 3.5.9 (4).

The little program presented here demonstrates four different ways
of defining a fixed-point type, and shows the resulting attributes
of each.

It also uncovered a GNAT bug in the 'image attribute for types
defined by an ordinary_fixed_point_definition and having the 'Small
attribute specified by an attribute_definition_clause.

Specifically, for a 64-bit fixed point type, the values in the
extreme regions of it range (i.e, values with a magnitude equal to
or greater than (10 ** 18) * T'Small -- where T'Small is an integer
power of 10) require 19 decimal digits to exactly express the value.
The 'image attribute of such values is always 0, and the next-to-last
digit is rounded.

The bug is being reported separately to ACT in a form suitable for
their automated e-mail processor.

The program output shows this bug.

-- begin source code --
with Ada.Text_IO;
procedure Fixed_Point is
   type Money_1 is delta 0.01 range 0.0 .. 100_000_000.00;
   type Money_2 is delta 0.01 digits 10 range 0.00 .. 10_000_000.00;
   type Money_3 is delta 0.01 range
     -0.01 * (2 ** 63 - 1) .. 0.01 * (2 ** 63 - 1);
   for Money_3'Small use 0.01;
   type Money_4 is delta 0.01 digits 10;
   type Integer_64 is range - 2 ** 63 .. 2 ** 63 - 1;
   Bad_Money : Money_3;
begin
   Ada.Text_IO.Put_Line
     ("Money_1'Small =" & Float'Image (Float (Money_1'Small)));
   Ada.Text_IO.Put_Line
     ("Money_1'Size  =" & Positive'Image (Money_1'Size));
   Ada.Text_IO.Put_Line
     ("Money_1'First =" & Money_1'Image (Money_1'First));
   Ada.Text_IO.Put_Line
     ("Money_1'Last  =" & Money_1'Image (Money_1'Last));
   Ada.Text_IO.New_Line;
   Ada.Text_IO.Put_Line
     ("Money_2'Small =" & Float'Image (Float (Money_2'Small)));
   Ada.Text_IO.Put_Line
     ("Money_2'Size  =" & Positive'Image (Money_2'Size));
   Ada.Text_IO.Put_Line
     ("Money_2'First =" & Money_2'Image (Money_2'First));
   Ada.Text_IO.Put_Line
     ("Money_2'Last  =" & Money_2'Image (Money_2'Last));
   Ada.Text_IO.New_Line;
   Ada.Text_IO.Put_Line
     ("Money_3'Small =" & Float'Image (Float (Money_3'Small)));
   Ada.Text_IO.Put_Line
     ("Money_3'Size  =" & Positive'Image (Money_3'Size));
   Ada.Text_IO.Put_Line
     ("Money_3'First =" & Money_3'Image (Money_3'First));
   Ada.Text_IO.Put_Line
     ("Money_3'Last  =" & Money_3'Image (Money_3'Last));
   Ada.Text_IO.New_Line;
   Ada.Text_IO.Put_Line
     ("Money_4'Small =" & Float'Image (Float (Money_4'Small)));
   Ada.Text_IO.Put_Line
     ("Money_4'Size  =" & Positive'Image (Money_4'Size));
   Ada.Text_IO.Put_Line
     ("Money_4'First =" & Money_4'Image (Money_4'First));
   Ada.Text_IO.Put_Line
     ("Money_4'Last  =" & Money_4'Image (Money_4'Last));
   Ada.Text_IO.New_Line;
   Ada.Text_IO.Put_Line
     ("Intger_64'Size  =" & Positive'Image (Integer_64'Size));
   Ada.Text_IO.Put_Line
     ("Intger_64'First =" & Integer_64'Image (Integer_64'First));
   Ada.Text_IO.Put_Line
     ("Intger_64'Lsst  =" & Integer_64'Image (Integer_64'Last));
   Ada.Text_IO.New_Line;
   Bad_Money := 10000000000000000.16;
   for I in 1 .. 30 loop
      Ada.Text_IO.Put_Line
     ("Bad_Money =" & Money_3'Image (Bad_Money));
      Bad_Money := Bad_Money - Money_3'Small;
   end loop;
end Fixed_Point;
-- end source code --

-- begin program output --
Money_1'Small = 7.81250E-03
Money_1'Size  = 34
Money_1'First = 0.00
Money_1'Last  = 100000000.00

Money_2'Small = 1.00000E-02
Money_2'Size  = 30
Money_2'First = 0.00
Money_2'Last  = 10000000.00

Money_3'Small = 1.00000E-02
Money_3'Size  = 64
Money_3'First =-92233720368547758.10
Money_3'Last  = 92233720368547758.10

Money_4'Small = 1.00000E-02
Money_4'Size  = 35
Money_4'First =-99999999.99
Money_4'Last  = 99999999.99

Intger_64'Size  = 64
Intger_64'First =-9223372036854775808
Intger_64'Lsst  = 9223372036854775807

Bad_Money = 10000000000000000.20
Bad_Money = 10000000000000000.10
Bad_Money = 10000000000000000.10
Bad_Money = 10000000000000000.10
Bad_Money = 10000000000000000.10
Bad_Money = 10000000000000000.10
Bad_Money = 10000000000000000.10
Bad_Money = 10000000000000000.10
Bad_Money = 10000000000000000.10
Bad_Money = 10000000000000000.10
Bad_Money = 10000000000000000.10
Bad_Money = 10000000000000000.10
Bad_Money = 10000000000000000.00
Bad_Money = 10000000000000000.00
Bad_Money = 10000000000000000.00
Bad_Money = 10000000000000000.00
Bad_Money = 10000000000000000.00
Bad_Money = 9999999999999999.99
Bad_Money = 9999999999999999.98
Bad_Money = 9999999999999999.97
Bad_Money = 9999999999999999.96
Bad_Money = 9999999999999999.95
Bad_Money = 9999999999999999.94
Bad_Money = 9999999999999999.93
Bad_Money = 9999999999999999.92
Bad_Money = 9999999999999999.91
Bad_Money = 9999999999999999.90
Bad_Money = 9999999999999999.89
Bad_Money = 9999999999999999.88
Bad_Money = 9999999999999999.87
-- end program output --

Al Christians <achrist@easystreet.com> wrote in message
news:383F808E.66464E08@easystreet.com...
> I ran your test with GNAT 3.12p under Windows NT on Pentium Pro.  I
> get the answer = 68.55.  Equally no good or even a little worse.
>
> Your fixed point numbers are all binary fixed point.  This is all
> according to the book; don't worry.
>
> Delta = 0.01 works out to use binary fixed point with 7 bits to the
> right of the binary point, ie numbers are represented as some number
> of 128ths; 1/128 is less than 0.01, so these are good to 2 decimal
> digits to the right of the decimal point.  Unfortunately, it looks
> like your 0.20 value gets represented by GNAT as 25/128, even though
> 26/128 is a little closer, neither is very close.  Whatever Ada you
> were using is using 26/128 and is a little more accurate than GNAT
> 3.12p, but there's a way around this either way (below).
>
> If I do this:
>
> a:     constant := 351.0;
> b:     constant := 1.0/5.0;
> d:     constant := a * b;
> c:     constant money := d;
>
> Then c comes out with the right value of 70.2.  a, b, and
> d, are each of type universal_real, with beaucoups of significant
> digits, and therefore c comes out ok.
>
>
> But if I do this:
>
> a:     constant := 351.0;
> b:     constant := 1.0/5.0;
> c:     constant money := a * b;
>
> Then c still comes out 68.55.  Looks like the a and b get converted
> to the money type before they get multiplied.  Ouch.
>
> But to make money a decimal fixed point type type, do this:
>
> -----------------------------------------------------------
>
> with Ada.Text_IO;
>
> procedure Money_Test is
>
> type money is delta 0.01 digits 10 range 0.0..10_000_000.00;
>
> a:     money;
> b:     money;
> c:     money;
>
> package money_io is new ada.text_io.decimal_io(money);
>
>
> begin
> a     := 351.0;
> b     := 0.20;
> c     := (a * b);
> money_io.put(c);  -- Prints 70.2
> end Money_Test;
>
> --------------------------------------------------------------
>
> This gives the right answer with no error.  The range constraint
> on the money type is optional; the digits + delta part combined
> make the numbers act like decimal numbers.
>
>
>
> Al
>
>
> Nap wrote:
> >
> > does anyone know why mutiplication between fixed type in ada produce a
> > big round off error?
> >
> > type money is delta 0.01 range 0.0..100_000_000.00;
> > a, b, c : money;
> >
> > package money_io is new ada.text_io.fixed_io(money);
> >
> > a := 351.00;
> > b := 0.20;
> > c := a * b;
> >
> > money_io.put(c);
> >
> > -- the output should be 70.2 but it prints 71.3 instead.
> > -- this is so frustrating. typecasting (back to float) doesn't help
> > either.
> >
> > Thanks,
> > Nap






^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: fixed type (delta) in ada
  1999-11-28  0:00 ` Robert Dewar
@ 1999-11-27  0:00   ` Al Christians
  1999-11-28  0:00     ` Preben Randhol
                       ` (2 more replies)
  0 siblings, 3 replies; 17+ messages in thread
From: Al Christians @ 1999-11-27  0:00 UTC (permalink / raw)




Robert Dewar wrote:
> 
> In article <383f6dbb.22609744@news.tstonramp.com>,
>   nap@nobody.com (Nap) wrote:
> > does anyone know why mutiplication between fixed type in ada
> produce a
> > big round off error?
> >
> > type money is delta 0.01 range 0.0..100_000_000.00;
> > a, b, c : money;
> >
> > package money_io is new ada.text_io.fixed_io(money);
> >
> > a := 351.00;
> > b := 0.20;
> > c := a * b;
> >
> > money_io.put(c);
> >
> > -- the output should be 70.2 but it prints 71.3 instead.
> > -- this is so frustrating. typecasting (back to float) doesn't
> help
> > either.
> 
> No, the output should be 71.3, and this is what is expected. 

So, why does GNAT 3.12p give 68.55?


Al




^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: fixed type (delta) in ada
  1999-11-28  0:00     ` Florian Weimer
@ 1999-11-28  0:00       ` Al Christians
  1999-11-29  0:00         ` Preben Randhol
  0 siblings, 1 reply; 17+ messages in thread
From: Al Christians @ 1999-11-28  0:00 UTC (permalink / raw)


Ok. I see that there are two values in the perfect result 
set.  No problem.  I see that in the ARM.  But it would be 
nice if the compiler would pick out the result that is more 
perfect, ie closer to the actual value.  I see that this 
stuff is also leftover from Ada 83, retained to make it 
possible to preserve behavior of existing programs.  But 
since the choice of values out of the possible result set 
is  implementation dependent, that looks more like more 
like a broad license than a precise spec.  'This is what 
is expected' doesn't explain it as well as 'this is one 
result that is allowed'.  Thanks.

Next question: I haven't seen where it says that

Money_Io.Put(0.20 * 351.0);

Should put 68.55, which is what GNAT 3.12p does.  My guess 
would be that 0.20 * 351.0 should be a static expression of 
type universal real, which should convert to type Money 
equal to 70.2 within +/- 0.01.  Is it according to the LRM 
to convert both the 0.20 and 351.0 to the Money type before 
doing the multiply?  Any other explanations?


Al



Florian Weimer wrote:
> 
> Al Christians <achrist@easystreet.com> writes:
> 
> > > No, the output should be 71.3, and this is what is expected.
> >
> > So, why does GNAT 3.12p give 68.55?
> 
> That's correct as well. 0.20 can be represented as 25/128 or 26/128
> (ARM 4.6(32), G.2.3(10), G.2.3(24)).




^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: fixed type (delta) in ada
  1999-11-27  0:00 fixed type (delta) in ada Nap
  1999-11-26  0:00 ` Al Christians
  1999-11-28  0:00 ` fixed type (delta) in ada Nick Roberts
@ 1999-11-28  0:00 ` Robert Dewar
  1999-11-27  0:00   ` Al Christians
  2 siblings, 1 reply; 17+ messages in thread
From: Robert Dewar @ 1999-11-28  0:00 UTC (permalink / raw)


In article <383f6dbb.22609744@news.tstonramp.com>,
  nap@nobody.com (Nap) wrote:
> does anyone know why mutiplication between fixed type in ada
produce a
> big round off error?
>
> type money is delta 0.01 range 0.0..100_000_000.00;
> a, b, c : money;
>
> package money_io is new ada.text_io.fixed_io(money);
>
> a := 351.00;
> b := 0.20;
> c := a * b;
>
> money_io.put(c);
>
> -- the output should be 70.2 but it prints 71.3 instead.
> -- this is so frustrating. typecasting (back to float) doesn't
help
> either.


No, the output should be 71.3, and this is what is expected. You
used a binary fixed point type, so you are working with binary
numbers not decimal numbers. You need to read up more on the
details of how fixed point works, or indeed you will frustrated
yourself! Most likely you should be using decimal types (look
up decimal types in the RM or in any good Ada text book).


Sent via Deja.com http://www.deja.com/
Before you buy.




^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: fixed type (delta) in ada
  1999-11-27  0:00 fixed type (delta) in ada Nap
  1999-11-26  0:00 ` Al Christians
@ 1999-11-28  0:00 ` Nick Roberts
  1999-11-30  0:00   ` Simon Wright
  1999-11-28  0:00 ` Robert Dewar
  2 siblings, 1 reply; 17+ messages in thread
From: Nick Roberts @ 1999-11-28  0:00 UTC (permalink / raw)


Nap wrote:
> 
> does anyone know why mutiplication between fixed type in ada produce a
> big round off error?
> ...

Do you want the short answer or the long answer, Nap?

The short version of the long answer is: the 'small' chosen for the type
'money' will be a power of two (e.g. 1/128); 0.20 will therefore not
have an exact representation when converted to the type 'money'; this
inexact representation of 0.20 will therefore produce an inexact result
after multiplication.

The short version of the short answer is: use a decimal type instead of
a fixed type (example follows).

   type Money is delta 0.01 digits 11;

Problem solved.

-- 
Nick Roberts
http://www.adapower.com/lab/adaos
Always call for the professionals. (If they don't help, call for me ;-)





^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: fixed type (delta) in ada
  1999-11-27  0:00   ` Al Christians
  1999-11-28  0:00     ` Preben Randhol
@ 1999-11-28  0:00     ` Florian Weimer
  1999-11-28  0:00       ` Al Christians
  1999-11-29  0:00     ` Robert Dewar
  2 siblings, 1 reply; 17+ messages in thread
From: Florian Weimer @ 1999-11-28  0:00 UTC (permalink / raw)


Al Christians <achrist@easystreet.com> writes:

> > No, the output should be 71.3, and this is what is expected. 
> 
> So, why does GNAT 3.12p give 68.55?

That's correct as well. 0.20 can be represented as 25/128 or 26/128
(ARM 4.6(32), G.2.3(10), G.2.3(24)).




^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: fixed type (delta) in ada
  1999-11-27  0:00   ` Al Christians
@ 1999-11-28  0:00     ` Preben Randhol
  1999-11-28  0:00     ` Florian Weimer
  1999-11-29  0:00     ` Robert Dewar
  2 siblings, 0 replies; 17+ messages in thread
From: Preben Randhol @ 1999-11-28  0:00 UTC (permalink / raw)


Al Christians <achrist@easystreet.com> writes:

| Robert Dewar wrote:
| > No, the output should be 71.3, and this is what is expected. 
| 
| So, why does GNAT 3.12p give 68.55?

I also got 68.55 on GNAT 3.12p on a Redhat 6.1 Linux system.

Btw. after using the other solution which gave 70.2, I noticed that
if I changed the numbers so I got a product like: 80.3198 (on a
calculator) it was given as 80.31. This is expected, but how does one
get Ada to round off the value 80.3198 to 80.32?

-- 
Preben Randhol                     "Marriage is when you get to keep
[randhol@pvv.org]                   your girl and don't have to give
[http://www.pvv.org/~randhol/]      her back to her parents." (Eric, 6)




^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: fixed type (delta) in ada
  1999-11-29  0:00         ` Preben Randhol
@ 1999-11-29  0:00           ` Al Christians
  1999-11-29  0:00             ` Preben Randhol
  0 siblings, 1 reply; 17+ messages in thread
From: Al Christians @ 1999-11-29  0:00 UTC (permalink / raw)


I don't see anything in Barnes that matches my example very well.
I'll guess that the compiler sees Money_Io.Put(351.00 * 0.20) and
decides that it has to find a multiplication operator that yields
a Money result to match the type of Money_Io.Put's parameter. The 
only possibility is to multiply two Money's together, so the 
351.00 and 0.20 get converted automatically before the multiply,
producing the 68.55 result. Money_Io.Put(Money(351.00 * 0.20)) will 
give the more accurate 70.2 result. 


Al

Preben Randhol wrote:
> 
> Al Christians <achrist@easystreet.com> writes:
> 
> | Next question: I haven't seen where it says that
> |
> | Money_Io.Put(0.20 * 351.0);
> |
> | Should put 68.55, which is what GNAT 3.12p does.  My guess
> | would be that 0.20 * 351.0 should be a static expression of
> | type universal real, which should convert to type Money
> | equal to 70.2 within +/- 0.01.  Is it according to the LRM
> | to convert both the 0.20 and 351.0 to the Money type before
> | doing the multiply?  Any other explanations?
> 
> It has to do with fixed point types and Decimal types (the prior gives
> 68.55 the latter gives 70.2). If available see "Programming in Ada 95"
> 2.ed by John Barnes (ISBN: 0-201-34293-6) chapter 15.5 and 15.6.
> --
> Preben Randhol -- [randhol@pvv.org] -- [http://www.pvv.org/~randhol/]
> "Det eneste trygge stedet i verden er inne i en fortelling."
>                                              -- Athol Fugard




^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: fixed type (delta) in ada
  1999-11-27  0:00   ` Al Christians
  1999-11-28  0:00     ` Preben Randhol
  1999-11-28  0:00     ` Florian Weimer
@ 1999-11-29  0:00     ` Robert Dewar
  1999-11-29  0:00       ` Al Christians
  2 siblings, 1 reply; 17+ messages in thread
From: Robert Dewar @ 1999-11-29  0:00 UTC (permalink / raw)


In article <38409C87.69EC865@easystreet.com>,
  Al Christians <achrist@easystreet.com> wrote:
> > No, the output should be 71.3, and this is what is expected.
>
> So, why does GNAT 3.12p give 68.55?
>
> Al
>

That's also an allowed output value in this case!


Sent via Deja.com http://www.deja.com/
Before you buy.




^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: fixed type (delta) in ada
  1999-11-29  0:00     ` Robert Dewar
@ 1999-11-29  0:00       ` Al Christians
  1999-11-29  0:00         ` Lutz Donnerhacke
  0 siblings, 1 reply; 17+ messages in thread
From: Al Christians @ 1999-11-29  0:00 UTC (permalink / raw)


How about this one:

---------------------------------------------------------

with Ada.Text_Io;

procedure Money_Test is 

   -- type money is delta 0.01 digits 10 range 0.0..10_000_000.00;
   type Money is delta 0.01 range 0.0 .. 10_000_000.00; 

   -- package money_io is new ada.text_io.decimal_io(money);
   package Money_Io is new Ada.Text_Io.Fixed_Io(Money);

   F : Long_Float := 0.0300000000000000;  

begin
   Money_Io.Put(Money(F));                   -- GNAT 3.12p Puts 0.03
   Money_Io.Put(Money(0.0300000000000000));  -- GNAT 3.12p Puts 0.02 
end Money_Test;

----------------------------------------------------------------

I suppose that 0.02 and 0.03 are each allowed, but I find the
inconsistency a little unexpected.


Al  


Robert Dewar wrote:
> 
> In article <38409C87.69EC865@easystreet.com>,
>   Al Christians <achrist@easystreet.com> wrote:
> > > No, the output should be 71.3, and this is what is expected.
> >
> > So, why does GNAT 3.12p give 68.55?
> >
> > Al
> >
> 
> That's also an allowed output value in this case!
>




^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: fixed type (delta) in ada
  1999-11-29  0:00       ` Al Christians
@ 1999-11-29  0:00         ` Lutz Donnerhacke
  1999-11-29  0:00           ` Preben Randhol
  0 siblings, 1 reply; 17+ messages in thread
From: Lutz Donnerhacke @ 1999-11-29  0:00 UTC (permalink / raw)


* Al Christians wrote:
>   F : Long_Float := 0.0300000000000000;  

First convertion. Might be 0.0300001244 afterwards.

>   Money_Io.Put(Money(F));                   -- GNAT 3.12p Puts 0.03

Second convertion.

>   Money_Io.Put(Money(0.0300000000000000));  -- GNAT 3.12p Puts 0.02 

A single convertion.

>I suppose that 0.02 and 0.03 are each allowed, but I find the
>inconsistency a little unexpected.

Of course. Playing near T'Small is hazardous.




^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: fixed type (delta) in ada
  1999-11-28  0:00       ` Al Christians
@ 1999-11-29  0:00         ` Preben Randhol
  1999-11-29  0:00           ` Al Christians
  0 siblings, 1 reply; 17+ messages in thread
From: Preben Randhol @ 1999-11-29  0:00 UTC (permalink / raw)


Al Christians <achrist@easystreet.com> writes:

| Next question: I haven't seen where it says that
| 
| Money_Io.Put(0.20 * 351.0);
| 
| Should put 68.55, which is what GNAT 3.12p does.  My guess 
| would be that 0.20 * 351.0 should be a static expression of 
| type universal real, which should convert to type Money 
| equal to 70.2 within +/- 0.01.  Is it according to the LRM 
| to convert both the 0.20 and 351.0 to the Money type before 
| doing the multiply?  Any other explanations?

It has to do with fixed point types and Decimal types (the prior gives
68.55 the latter gives 70.2). If available see "Programming in Ada 95"
2.ed by John Barnes (ISBN: 0-201-34293-6) chapter 15.5 and 15.6. 
-- 
Preben Randhol -- [randhol@pvv.org] -- [http://www.pvv.org/~randhol/]     
"Det eneste trygge stedet i verden er inne i en fortelling." 
                                             -- Athol Fugard




^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: fixed type (delta) in ada
  1999-11-29  0:00           ` Al Christians
@ 1999-11-29  0:00             ` Preben Randhol
  0 siblings, 0 replies; 17+ messages in thread
From: Preben Randhol @ 1999-11-29  0:00 UTC (permalink / raw)


Al Christians <achrist@easystreet.com> writes:

| I don't see anything in Barnes that matches my example very well.
| I'll guess that the compiler sees Money_Io.Put(351.00 * 0.20) and
| decides that it has to find a multiplication operator that yields
| a Money result to match the type of Money_Io.Put's parameter. The 
| only possibility is to multiply two Money's together, so the 
| 351.00 and 0.20 get converted automatically before the multiply,
| producing the 68.55 result. Money_Io.Put(Money(351.00 * 0.20)) will 
| give the more accurate 70.2 result. 


With my limited knowledge of Ada95 I would assume that as
Money_IO.Put() expects a type of Money the operator "*" is the
derivative function: 

function "*" (Left,Right : Money'Base) return Money'Base; 

(Not quite sure if 'Base is needed) And thus uses this. 
As is the latter example it uses:

function "*" (Left,Right : Float'Base) return Float'Base;

as Money will type cast it from Float to Money.

Is this correct? 

-- 
Preben Randhol -- [randhol@pvv.org] -- [http://www.pvv.org/~randhol/]     
"Det eneste trygge stedet i verden er inne i en fortelling." 
                                             -- Athol Fugard




^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: fixed type (delta) in ada
  1999-11-29  0:00         ` Lutz Donnerhacke
@ 1999-11-29  0:00           ` Preben Randhol
  0 siblings, 0 replies; 17+ messages in thread
From: Preben Randhol @ 1999-11-29  0:00 UTC (permalink / raw)


lutz@iks-jena.de (Lutz Donnerhacke) writes:

| * Al Christians wrote:
| >   F : Long_Float := 0.0300000000000000;  
| 
| First convertion. Might be 0.0300001244 afterwards.

It prints out as 3.00000000000000E-02 (if you use Ada.Long_Float_Text_IO (GNAT))
 
| >   Money_Io.Put(Money(F));                   -- GNAT 3.12p Puts 0.03
| 
| Second convertion.
| 
| >   Money_Io.Put(Money(0.0300000000000000));  -- GNAT 3.12p Puts 0.02 
| 
| A single convertion.

Even Money_Io.Put(Money(Long_Float(0.0300000000000000))); gives 0.02

| Of course. Playing near T'Small is hazardous.

I would guess so :-)
-- 
Preben Randhol -- [randhol@pvv.org] -- [http://www.pvv.org/~randhol/]     
         "Det eneste trygge stedet i verden er inne i en fortelling." 
                                                      -- Athol Fugard




^ permalink raw reply	[flat|nested] 17+ messages in thread

* Re: fixed type (delta) in ada
  1999-11-28  0:00 ` fixed type (delta) in ada Nick Roberts
@ 1999-11-30  0:00   ` Simon Wright
  0 siblings, 0 replies; 17+ messages in thread
From: Simon Wright @ 1999-11-30  0:00 UTC (permalink / raw)


Nick Roberts <nickroberts@callnetuk.com> writes:

> Nap wrote:
> > 
> > does anyone know why mutiplication between fixed type in ada produce a
> > big round off error?
> > ...
> 
> Do you want the short answer or the long answer, Nap?
> 
> The short version of the long answer is: the 'small' chosen for the type
> 'money' will be a power of two (e.g. 1/128); 0.20 will therefore not
> have an exact representation when converted to the type 'money'; this
> inexact representation of 0.20 will therefore produce an inexact result
> after multiplication.
> 
> The short version of the short answer is: use a decimal type instead of
> a fixed type (example follows).
> 
>    type Money is delta 0.01 digits 11;
> 
> Problem solved.

Alternatively,

  Money_Small : constant := 0.01;
  type Money is delta Money_Small range 0.0..100_000_000.00;
  for Money'Small use Money_Small;

gives the expected result for the case in question.




^ permalink raw reply	[flat|nested] 17+ messages in thread

end of thread, other threads:[~1999-11-30  0:00 UTC | newest]

Thread overview: 17+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
1999-11-27  0:00 fixed type (delta) in ada Nap
1999-11-26  0:00 ` Al Christians
1999-11-27  0:00   ` fixed type (delta) in ada and GNAT bug David C. Hoos, Sr.
1999-11-28  0:00 ` fixed type (delta) in ada Nick Roberts
1999-11-30  0:00   ` Simon Wright
1999-11-28  0:00 ` Robert Dewar
1999-11-27  0:00   ` Al Christians
1999-11-28  0:00     ` Preben Randhol
1999-11-28  0:00     ` Florian Weimer
1999-11-28  0:00       ` Al Christians
1999-11-29  0:00         ` Preben Randhol
1999-11-29  0:00           ` Al Christians
1999-11-29  0:00             ` Preben Randhol
1999-11-29  0:00     ` Robert Dewar
1999-11-29  0:00       ` Al Christians
1999-11-29  0:00         ` Lutz Donnerhacke
1999-11-29  0:00           ` Preben Randhol

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