Ada Fundamentals - Primitive Types
Overview
- Integer and Float Types
- Integer'Image and Float'Image
- Ada.Integer_Text_io; Ada.Float_Text_io
- 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
Package Ada.Integer_Text_IO
- Integer input and output routines
- Name comes from outputing an integer as text
- Routine
put
is overloaded (ie same name
but different parameters)
- Ada.Text_IO.put("HI");
- Ada.Integer_Text_IO.put(i);
- 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
Integer Input: Ada.Integer_Text_IO.get
- 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;
with Ada.Integer_Text_IO; use Ada.Integer_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;
What's unusual about get
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
Package Ada.Float_Text_IO
- 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