From: vincent.diemunsch on
Hi everybody,

I wonder why Ada uses "/" to express the integer division and not
"div".
This leads to the fact that an expression like 4/3*6 that any decent
calculator
would evaluate as 8 is in Ada evaluated as 6 !!! That is a shame :-).

Therefore, I propose the following, for a new revision of the
language :
- discard the function "/" (left, right : Integer) return Integer and
replace it by the operator "div",
that sounds quite logical with the existing "rem" and "mod".
- add a fraction package with a function "/" (left, right :
Integer'base) return Fraction; as constructor.

Then when compiling "n : integer := 4/3*6;" an error will occur,
because the result will be the fraction
8/1 and not an integer. The sentence could then be changed in
EITHER "n : integer := (4 div 3)*6" that explicitly states that the
result will be 6.
OR "n : integer := Rounding (4/3*6);

I think this solution is safe and will add simplicity and precision to
integer operations.
Moreover, this correct handling of integer computation will allow
compilers to make optimizations
like for instance simplifying expressions like "2/3 * n * 6 * i" ->
"4*n*i"

Do you think I could summit this to the next revision of the
language ?
If yes, how ?

Vincent

Here is a example of a fraction package :

--------------------------------------------------------------------------------
-- This package is a simple implementation of common fractions.
--
-- Copyright (C) 2009 Vincent DIEMUNSCH.
-- GNU General Public License.
--
-- This program is free software: you can redistribute it and/or
modify it under
-- the terms of the GNU General Public License as published by the
Free Software
-- Foundation, either version 3 of the License, or (at your option)
any later
-- version.
--
-- This file is distributed in the hope that it will be useful, but
WITHOUT ANY
-- WARRANTY; without even the implied warranty of MERCHANTABILITY or
FITNESS FOR
-- A PARTICULAR PURPOSE. See the GNU General Public License for more
details.
--
-- You should have received a copy of the GNU General Public License
along with
-- this program. If not, see <http://www.gnu.org/licenses/>.
--------------------------------------------------------------------------------
--
-- REVISION HISTORY :
-- Version 1.0, Author : V. DIEMUNSCH, date : 12/01/2009, Creation
-- Version 1.1, Author : V. DIEMUNSCH, date : 18/05/2009, Created 2
GCD functions in body
-- Version 1.2, Author : V. DIEMUNSCH, date : 27/06/2009, made type
Fraction private
-- Version 1.3, Author : V. DIEMUNSCH, date : 30/06/2009, fixed a
major bug in Complex_GCD !

package Fractions is

Max : constant := Integer'Last;
subtype Numerator is Integer; -- range - Max .. + Max;
subtype Denominator is Positive; -- range 1 .. + Max;

type Fraction is private;

-- The type Fraction is private, to ensure that a fraction is
always in canonical form.
-- The canonical form means that the denominator and the numerator
have no common factors,
-- and that the denominator is positive. Zero has the unique
representation 0/1.
-- The best way to create a new fraction is to use the following
function "/",
-- that canonicalizes the fraction using a binary GCD algorithm.
-- After each operation the fraction is canonicalized, sometimes
using a smart
-- algorithm to reduce computation speed. Setting directly the
value of the
-- Numerator and Denominator can avoid these repetitive
computations.
-- But then it is the responsibility of the user that the assigned
values have
-- no common factors.

function "/" (Left : Numerator; Right : Denominator) return
Fraction;
-- The Fraction returned is in canonical form.

function Num (F : Fraction) return Numerator;
function Den (F : Fraction) return Denominator;

function Set_Canonical_Fraction (Left : Numerator; Right :
Denominator) return Fraction;
-- Bypass canonicalization ... So it is the caller responsability
-- to make sure the fraction is in canonical form !
pragma Inline (Num, Den, Set_Canonical_Fraction);

-- GCD :
function GCD (n, m : Positive) return Positive;

function Image (F : Fraction) return String;

----------------------------
-- "Standard" description --
----------------------------

-- (Mimics package Standard)
-- The predefined operators for this type are as follows:

function "=" (Left, Right : Fraction) return Boolean;
function "<" (Left, Right : Fraction) return Boolean;
function "<=" (Left, Right : Fraction) return Boolean;
function ">" (Left, Right : Fraction) return Boolean;
function ">=" (Left, Right : Fraction) return Boolean;

function "+" (Right : Fraction) return Fraction;
function "-" (Right : Fraction) return Fraction;
function "abs" (Right : Fraction) return Fraction;

function "+" (Left, Right : Fraction) return Fraction;
function "-" (Left, Right : Fraction) return Fraction;
function "*" (Left, Right : Fraction) return Fraction;
function "/" (Left, Right : Fraction) return Fraction;

function inv (Right : Fraction) return Fraction;

function "**" (Left : Fraction; Right : Integer'Base) return
Fraction;

-- with standard integers:
function "*" (Left : Integer'Base; Right : Fraction) return
Fraction;
function "*" (Left : Fraction; Right : Integer'Base) return
Fraction;
function "/" (Left : Integer'Base; Right : Fraction) return
Fraction;
function "/" (Left : Fraction; Right : Integer'Base) return
Fraction;

function div (left, right : Integer) return Integer;

function Floor (F : Fraction) return Integer;
function Ceiling (F : Fraction) return Integer;
function Rounding (F : Fraction) return Integer;
function Unbiased_Rounding (F : Fraction) return Integer;


-- with real types:

generic
type F is digits <>;
function To_Float (Q : Fraction) return F;

generic
type F is delta <>;
function To_Fixed_Point (Q : Fraction) return F;

private

type Fraction is record
Num : Numerator;
Den : Denominator;
end record;

end Fractions;

From: Dmitry A. Kazakov on
On Fri, 30 Apr 2010 23:52:18 -0700 (PDT), vincent.diemunsch(a)gmail.com
wrote:

> I wonder why Ada uses "/" to express the integer division and not
> "div".

Because in most languages / denotes "integer division", which mathematical
integer lack (:-)).

> This leads to the fact that an expression like 4/3*6 that any decent calculator
> would evaluate as 8 is in Ada evaluated as 6 !!! That is a shame :-).

1. The calculator uses reals, not integers.
2. There exist expression which cannot be evaluated (as decimal fractions
of finite length), e.g. 1.0/3.0
3. There exist operations not closed in R. So a "decent" calculator should
return j for sqrt(-1.0)
4. There exist operations not closed in C, e.g. multi-valued functions. A
"decent" calculator must return a set of values?

> - discard the function "/" (left, right : Integer) return Integer and
> replace it by the operator "div",

AFAIK, ARG does not introduce backward incompatibilities unless absolutely
necessary (in their opinion (:-)). I doubt that / could fall under this
category.

> that sounds quite logical with the existing "rem" and "mod".
> - add a fraction package with a function "/" (left, right :
> Integer'base) return Fraction; as constructor.

Arguably better would be "div" as a full division, e.g. returning a tuple
of the result and the remainder. In both cases there is a problem that the
result type (be it fraction, tuple, rational etc) shall be defined
(inferred) for each integer type including user-defined ones. Ada lacks any
mechanics for this.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
From: Georg Bauhaus on
On 5/1/10 8:52 AM, vincent.diemunsch(a)gmail.com wrote:
> Hi everybody,
>
> I wonder why Ada uses "/" to express the integer division and not
> "div".
> This leads to the fact that an expression like 4/3*6 that any decent
> calculator
> would evaluate as 8 is in Ada evaluated as 6 !!! That is a shame :-).

High school assumptions will haunt us forever. :-)

Maybe von Neumann's sceptic remark about Fortran made in 1954
applies to Ada's operator notation, too.

Mold it like this: The trouble originates when a programmer
forgets about the important fact that the thing to be
programmed is a computing apparatus. As such, it has its own
mathematical structures. As such, it must be given proper
attention. Formal attention. Then it will turn out to be more
useful and enrich our computing potential.

Surely approaching a computing apparatus with casually
expressed formulas such as 4/3*6 fails on both accounts:
Seen across languages, they are not well defined textual
expressions of a program. Rather, they hint at mathematical
ideas. The interpretation 8 as the value of 4/3*6 is only
one of many. But many possible interpretations would not seem
to be a good thing in the case of free-standing literals if
you want to achieve clarity of expression. 8 becomes a
possible interpretation only because of a m�lange of evaluation
strategies from which we will have to choose. Again and again.
But how should we choose when writing formal programs, e.g. in Ada?

1) In programming, mathematics, and elsewhere, / and * are
massively overloaded symbols. Why incur overload resolution
into expressions involving literals when instead we could
add clarity by simply using typed literals and brackets?
(Resolving overridings or similar would improve litte for
untyped literals, I think.) Strategy: Say what you mean.

2) There is only implicit association. Write in two or three
programming languages regularly and maybe you start adding
brackets routinely. Strategy: Add brackets.

LISP, without infix notation, is much less dangerous in this
regard.

With clarity of interpretation in mind, having typed fraction
literals seems as interesting as ever.
From: Jeffrey R. Carter on
vincent.diemunsch(a)gmail.com wrote:
>
> Do you think I could summit this to the next revision of the
> language ?

Yes, certainly. Anyone may submit suggestions for revising the language.
However, changes that make existing legal Ada programs invalid or have different
behavior are rarely accepted. Given that Ada has used "/" for integer division
for 30 years, this is unlikely to be accepted.

> If yes, how ?

By sending e-mail to ada-comment(a)ada-auth.org, as described in the Introduction
to the ARM:

http://www.adaic.org/standards/05rm/html/RM-0-3.html

--
Jeff Carter
"Hold your temper. Count ten.... Now let 'er go.
You got a good aim."
Never Give a Sucker an Even Break
105
From: Gene on
On May 1, 2:52 am, "vincent.diemun...(a)gmail.com"
<vincent.diemun...(a)gmail.com> wrote:
> Hi everybody,
>
> I wonder why Ada uses "/" to express the integer division and not
> "div".
> This leads to the fact that an expression like 4/3*6 that any decent
> calculator
> would evaluate as 8 is in Ada evaluated as 6 !!! That is a shame :-).
>
> Therefore, I propose the following, for a new revision of the
> language :
> - discard the function "/" (left, right : Integer) return Integer and
> replace it by the operator "div",
> that sounds quite logical with the existing "rem" and "mod".
> - add a fraction package with a function "/" (left, right :
> Integer'base) return Fraction; as constructor.
>
> Then when compiling "n : integer := 4/3*6;" an error will occur,
> because the result will be the fraction
> 8/1 and not an integer. The sentence could then be changed in
> EITHER "n : integer := (4 div 3)*6" that explicitly states that the
> result will be 6.
> OR        "n : integer := Rounding (4/3*6);
>
> I think this solution is safe and will add simplicity and precision to
> integer operations.
> Moreover, this correct handling of integer computation will allow
> compilers to make optimizations
> like for instance simplifying expressions like "2/3 * n * 6 * i" ->
> "4*n*i"
>
> Do you think I could summit this to the next revision of the
> language ?
> If yes, how ?
>
> Vincent

[snip]

I tend to agree that "div" would be better than "/" as a matter of
truth in advertising. When Ada 83 was designed, many languages in
common use would evaluate 2/3 as integer zero (FORTRAN, C, C++, later
Java, ...). Pascal was alone, AFAICR, in providing "div" (Modula?).
The "div" seems better than "/" for the same reason I generally like
Ada for teaching new programmers in other aspects: it provides a clue
that the most common meaning of "/", division over Real numbers, which
people learn from from a very early age, does not apply here.
Consequently it decreases by some small amount the probability that a
second's inattention will produce a program bug, such as writing 2 / 3
* n instead of 2 * n / 3. It's harder, at lease for me, to write 2
div 3 * n without noticing the mistake. This aligns with Ada's
consistency in id-as-value, in/out parameters, and other clean,
orthagonal features that also reduce the cognitive leap between
program text and semantics.

OTOH, your suggestion probably can't be implemented because it
invalidates so much existing code. Additionally, your version of
Fraction isn't generally useful because 32- or even 64-bit N/D
rationals overflow quickly under multiplication in most realistic
settings, even if lowest terms are maintained by factoring out gcds.
In practice, you'd need to use a numerics tower including bignums,
such as Common Lisp does.

Cheers.