From: vincent.diemunsch on 1 May 2010 02:52 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 1 May 2010 05:25 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 1 May 2010 06:46 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 1 May 2010 12:26 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 2 May 2010 17:33
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. |