Overview

• Integer and Float Types
• Integer'Image and Float'Image

• Other Primitive Types
• Very Strong Type Checking
• Type Conversions
• Language comparison
• Subtype conversion
• Operators

Example Program (From Last Year)

• Let's get some practice by writing a simple program

• Let's sum a group of integers and calculate and print their average

• First we'll input the number of numbers and read that many numbers

• Can we format the average of the numbers

• What if the numbers are floating point?

• Let's make sure the number of numbers is non-negative

• Now let's read until eof

Integer'Image - An Attribute of type Integer

• Similar to Java `toString()` method

• Resulting string includes space for a sign.
• This results in a leading blank for positive numbers

• 'Image is an attribute of the type Integer

• Most built-in types have 'Image attribute

• Integer input and output routines
• Name comes from outputing an integer as text

• Routine `put` is overloaded (ie same name but different parameters)

• If two packages have the same routine with the same parameter list, then the package name must be used to disambiguate the routines
• Can a single package have two routines with the same name and same parameter list?

• Minimum width - eg put(i, 1)
• If given 2 parameters, the second is the minimum width
• Pads on left with blanks if needed
• Examples:
• ```                    i := 37;
--12345678901
put(i, 5); --   37
put(i, 1); --37
put(i);    --         37
-- Default width is 11
```

• How to input an Integer?
• Consider this Java:
• ```            Scanner s = ...
int i = s.nextInt();  // nextInt returns an int
S.o.println(i);
```
• And this similar Ada code
• ```            with Ada.Text_IO; use  Ada.Text_IO;
procedure getInt is
i: Integer := 2;
begin
put("Enter an integer: ");  -- Let's use a prompt
get(i);                     -- Now input the int
put(i);
new_line;
end getInt;
```
• Functions are used as values
• Procedures are used as statements
• Procedure parameters can be changed!

Size Attribute

• How can we tell how many bits a variable takes?

• Attribute size

• Example: ` Integer'size`

Sizes of Integer Types

• Sizes of types are NOT defined by the language (unlike Java)

• Floating point sizes
• Values of type Integer are typically 32 bits
• Values of type Long_Integer are 64 bits (on gnat)
• Values of type Long_Long_Integer are 64 bits (on gnat)

Floating Point Types

• Floating point sizes (eg value of Float'size)
• Type ` Float` - 32 bits on gnat
• Type ` Long_Float` - 64 bits on gnat
• Type ` Long_Long_Float` - 96 bits on gnat

• Floating point types trade precision for range
• 32 bit Integer has 10 significant digits in range ± 1010
• 32 bit Float has about 6 significant digits for numbers as small as ± 10-26 and as large as ± 1025

• Some attributes for floating point types:
• float'small - smallest possible (positive) value
• float'large - largest possible value
• float'digits - number of digits of precision

• Contains routines for IO of floating point types

• put(x)
• default format: scientific notation

• put(x, 3, 4, 1): fore, aft, exp
• fore: minimum digits to left of decimal point
• aft: digits to right of decimal point
• exp: digits in exponent - 0 means no exponent

Primitive Types

• Integer and Float are primitive types
• In this context, "primitive" means part of the language; that is, not user defined)

• Other primitive types include
• Character: 8 bit (Wide_Character: 16 bit Unicode, Wide_Wide_Character: 32 bit)
• Boolean: values ` true` and ` false`
• Positive: range 1 .. Integer'Last
• Natural: range 0 .. Integer'Last
• String

• Later we will see that
• Character and Boolean are Enumerated types
• String is an array of characters
• Positive and Natural are actually subtypes of Integer
• Where do we see subtypes in Java?
• Below we see difference in subtype conversion in Ada and Java

Another Meaning of Primitive

• What are the two kinds of types in Java?
• Reference type:
• variable stores a reference to a value
• automatic dereferencing
• Primitive: variable stores value itself

• Ada built-in types are primitive (ie not reference)
• Later we will see that a value of a primitive type can be a pointer

• User defined types
• In Java: all user defined types are ...
• In Ada: user defined types can be primitive

Very Strong Type Checking

• Ada has different and generally stronger type checking rules than Java

• Types of right and left sides of assignment must match

• x: Float := 3;  -- Compile error

• Java would do an implicit conversion

• Arithmetic operators must have the same types on both sides

• y := 2 + 3.0;   -- Compile error

• Java would do an implicit conversion

• Later we will see numeric subtypes that have more flexible rules:
• Ada will do implicit conversion on numeric subtypes (eg from natural to integer)

Explicit Type Conversion

• Example - this won't compile - it contains type mismatch:
• ```    i: Integer;
f, g: Float;
...
g := f + i;
```
• Ada will not do an implicit conversion between integer and float

• Example: the explicit type conversion fixes the type mismatch:
• ```    i: Integer;
f, g: Float;
...
i := 99;
...
g := f + Float(i);
-- float(i) returns the value of i as a float
--    that is, it returns 99.0
```
• In general, a type conversion uses the name of a type as if it were a function that takes a value of one type and returns a value of a different, related type

• Similar to a java type cast (eg g = f + (float) i;)

Language Comparison: Implicit and Explicit Type Conversion

• Ada will not do an implicit type conversion from integer to float

• Java will do an implicit type conversion from integer to float

• C will do an implicit type conversion from integer to float and float to integer

• C++ will do an implicit type conversion from integer to float

• C++ will do an implicit type conversion from float to integer and give a warning

Language Comparison: Type Conversion with Subtypes in Ada and Java

• Ada will do an implicit type conversion between a subtype of a type and the type (eg from natural to integer, and integer to natural)
• A constraint error is raised if the value of the parent type is not valid for the subtype

• Java has rules for subtypes and parent types with inheritance
• Parent myP; Child myC;
• myP = myC; //??
• myC = myP; //??

Operators: Precedence and Associativity

 Highest ** abs not exponent, absolute value, logical negation Multiplying * / mod rem mod and rem differ for negative numbers Unary adding + - Binary adding + - & & is string concatenation Relational = /= < <= > >= Note: not equal is /= rather than != Boolean (Lowest) and or xor xor is exclusive or

• All operators are left associative (but sometimes parens are required, anyway)

• Later we will see: in, and then, or else
• They are used like operators but they are not called operators

Examples using Arithmetic Operators

• 6 / 2 yields 3

• 6.0 / 2.0 yields 3.0

• 6.0 / 2 does not compile
• most operators require operands to be of the same type

• 2.0 ** 3 yields 8.0

• 2.0 ** (-3) yields 0.125 (ie 1/8)

Rem and Mod Operators

• Rem and Mod give the same result for positive operands

• Rem and Mod can differ for negative operands

• Table showing examples:
• ```    A   B |  A/B   A rem B  A mod B ||   A     B  |  A/B   A rem B   A mod B
------------------------------------------------------------------------------
10   5 |   2       0        0    || -10     5  |  -2       0         0
11   5 |   2       1        1    || -11     5  |  -2      -1         4
12   5 |   2       2        2    || -12     5  |  -2      -2         3
13   5 |   2       3        3    || -13     5  |  -2      -3         2
14   5 |   2       4        4    || -14     5  |  -2      -4         1
-------------------------------------------------------------------------
10  -5 |  -2       0        0    || -10    -5  |   2       0         0
11  -5 |  -2       1       -4    || -11    -5  |   2      -1        -1
12  -5 |  -2       2       -3    || -12    -5  |   2      -2        -2
13  -5 |  -2       3       -2    || -13    -5  |   2      -3        -3
14  -5 |  -2       4       -1    || -14    -5  |   2      -4        -4
```
• Careful: Rem and mod have higher precedence than unary minus so -3 mod 4 means -(3 mod 4)

Rem Operator

• Integer division and Rem work together so that this identity is true: A = (A / B) * B + A rem B

• Integer division truncates toward 0 [eg 7/2 = (-7)/(-2) = 3 and (-7)/2 = 7/(-2) = -3]

• Rem is designed to work with this definition [eg 7 rem 2 = 7 rem (-2) = 1 and (-7) rem 2 = -7 rem (-2) = -1]

• Example showing A = (A / B) * B + A rem B:
• ```                        (A / B) * B + A rem B
= (-7 / 2) * 2 + -7 rem 2
=    -3    * 2 +     -1
=         -6   +     -1
=             -7
```
• The result of A rem B has the sign of the Dividend

Mod Operator

• Mod provides modular behavior (ie clock arithmetic):
• Example: -9 mod 12 = 3 (ie go around the clock 9 hours counterclockwise).

• What is -9 rem 12?

• A mod B is always between 0 and B
• Thus, the result of Mod has the sign of the Divisor

• Does Mod satisfy the identity A = (A/B)*B + A mod B ?
• Not with the built in definition of / [ie A/B truncates toward 0 for integers A and B]
• Yes if A/B truncates toward minus infinity for ints A and B
• In other words, if A/B = integer(float'floor(float(A) / float(B)))

• Example using truncation toward minus infinity [eg using (-9)/12=-1]:
• ```
(-9/12) * 12 + -9 mod 12
=    -1   * 12 +     3
=        -12   +     3
=             -9
```

• Mod is designed so that A mod B = (A + K*B) mod B, for any integer K

• Mod is designed so that A = B*N + A mod B, for some integer N

A Final Word on Integer Division

• How is integer (eg 5 / 4) division defined in math?
• Answer: It gives a rational result, which then has an operator applied to it
• Example: 5/4 is the rational number one and one quarter
• In Ada, division of integers A and B is defined as trunc(A/B), for the rational number A/B [trunc removes the fractional part]

Rem and Mod and Other Languages

• In the C/C++/Java family, / is integer division and % is
• In the C/C++/Java family, / for integer division truncates toward 0
• % works with /, like the Ada rem operator

• In virtually all modern processors integer division truncates toward 0
• Most languages define integer division like Ada and Java, but other definitions exist!

Examples using Relational and Boolean Operators

• When `and` and `or` are mixed, parens are required (ie user must specify order of evaluation)

• Example: ```if (a < b or c < d) and e < f then```

• Parens are also required if multiple relational operators are used:
• Example:` if (a < b) = true then`

Example using String Concatenation Operator

```        put_line("Hello, this certainly is a "
& "really long line!");
```

Short Circuit: and then, or else

• `and then` and `or else` are short circuit versions of `and` and `or`

• Short circuit control forms don't evaluate the right operand if the result is known from the left operand

• Non-Short circuit operators always evaluate both operands

• Examples:
• ```
if d /= 0 and then (n / d) > 3 then ...

if x = null or else x.value = probe then ...
```
• Good for processing linked data structures!

• Java: What do these do?
• ```            if (a == b && c++ == d) ...

if (a == b &  c++ == d) ...
```

in Membership Test

```
if i in 1 .. 10 then
```