Monday, July 9, 2012

Float Data Types & Variables in C Programming Language

Integer and character data types are incapable of storing numbers with fractional parts. Depending on the precision required, C provides two variable types for computation with "floating point" numbers, i.e. numbers with a decimal (internally a binary) point. Such numbers are called floats because the binary point can only be represented in the binary- digits expansion of the number, in which it is made to "float" to the appropriate "position" for optimal precision. (You can immediately see the difficulty of imagining a binary "point" within any particular bit of a floating point word, which can contain only a 0 or a 1!) Typically, some of the leftmost bits of a floating point number store its characteristic (the positive or negative power of two to which it is raised), and the remaining its mantissa, the digits which comprise the number. In base 10, for example, if 2.3 is written as 0.0023 *103, the mantissa is 0.0023, and the characteristic (exponent) is 3.

Single precision floating point variables are declared by the float specification, for example:

float bank_balance = 1.234567E8;

/*En means 10 raised to the power n */

The scientific notation En, where the lowercase form en is also acceptable, is optional; one may alternatively write:

float bank_balance = 123456700.0;

Floats are stored in four bytes and are accurate to about seven significant digits; on PCs their range extends over the interval [E-38, E37].

It must never be lost sight of that the floating point numbers held in a computer's memory are at best approximations to real numbers. There are two reasons for this shortcoming. First, the finite extent of the word size of any computer forces a truncation or round-off of the value to be stored; whether a storage location is two bytes wide, or four, or even eight, the value stored therein can be precise only to so many binary digits.

Second, it is inherently impossible to represent with unlimited accuracy some fractional values as a finite series of digits preceded by a binary or decimal point. For example

1/7 = 0. 142857142857142857 ..... ad infinitum

As long as a finite number of digits is written after the decimal point, you will be unable to accurately represent the fraction 1/7. But rational fractions that expand into an infinite series of decimals aren't the only types of floating point numbers that are impossible to store accurately in a computer. Irrational numbers such as the square root of 2 have a periodic (non- repeating) expansions__there's no way that you can predict the next digit, as you could in the, expansion of 1/7 above, at any point in the series. Therefore it's inherently impossible to store such numbers infinitely accurately inside the machine. PI, the ratio of the circumference of any circle to its diameter, is another number that you cannot represent as a finite sequence of digits. It's not merely irrational, it's a transcendental number. (It cannot be the root of any algebraic equation with rational coefficients.) So an element of imprecision may be introduced by the very nature of the numbers to be stored.

Third, in any computation with floating point numbers, errors of round-off or truncation are necessarily introduced. For suppose you multiply two n-bit numbers; the result will in general be a 2n-bit number. If this number (2n) of bits is larger than the number of bits in the location which will hold the result, you will be forcing a large object into a small hole! Ergo, there'll be a problem! Some of it will just have to be chopped off. Therefore it is wisest to regard with a pinch of salt any number emitted by a computer as the result of a computation, that has a long string of digit-, after the decimal point. It may not be quite as accurate as it seems.

The %e, %f and %g format conversion characters are used in the scant () and printf () functions to read and print floating point numbers. %e (or %E) is used with floating point numbers in exponent format, while %g (or %G) may be used with floats in either format. %g (or %G) in the printf () outputs a float variable either as a string of decimal numbers including a decimal point, or in exponent notation, whichever is shorter. An uppercase E or G prints an uppercase E in the output. We shall be discussing more about format control in a later Unit.) Program 2.15 below finds the average of five numbers input from the keyboard, and print, it:

/* Program 1 */
#include <stdio.h>  
main()  
{   
 float val_1, val_2, val_3, val_4, val_5, total 0.0, avg;   
 pritf ("\nEnter first number...");   
 scanf ("%f", &val_1);   
 printf ("\nEnter third number...");  
 printf ("\nEnter second number...");   
 scanf ("%f', &,val_2);   
 scanf ("%f', &val_3);   
 printf ("\nEnter fourth number...");  
 scanf ("%f", &val_4);   
 avg = total / 5;  
 printf ("\nEnter fifth number...");   
 scanf ("%f", &val_5);  
 total = val_1 + val_2 + val_3 + val_4 + val_5;  
 printf ("\nThe average of the numbers you entered is: %f\n", avg);   
} 

Here's a sample conversation with the program:

Enter first number .. 32.4
Enter second number .. 56.7
Enter third number .. 78.3
Enter fourth number .. 67.8
Enter fifth number... -93.9
The average of the numbers you entered is: 28.260000

Character Data Types in C Programing Language

Character Data Types or variables are used to store single characters from the ASCII set. They're accommodated in a single byte. Character variables are declared and defined as in the statement below:

char bee = 'b', see = 'C', ccc;

This declaratory statement assigns the character constant 'b' to the char variable bee, and the character constant 'c' to the char variable named see. The char variable ccc is undefined.

Character constants are single characters. They must be enclosed in right single quotes. Escape sequences may be also assigned to character variables in their usual backslash notation, with the "compound character" enclosed in right single quotes. Thus the statement:

char nextline = '\n';

assigns the escape sequence for the newline character to the char variable nextilne. [In ANSI C a character constant is a sequence of one or more characters enclosed in single quotes. Precisely how the value of such a constant is to be interpreted is left to the implementation.]

Since character variables are accommodated in a byte, C regards chars as being a sub- range of ints, (the subrange that fits inside a byte) and each ASCII character is for all purposes equivalent to the decimal integer value of the bit picture which defines it. Thus 'A', of which the ASCII representation is 01000001, has the arithmetical value of 65 decimal. This is the decimal value of the sequence of bits 01000001, as you may easily verify. In other words, the memory representation of the char constant 'A' is indistinguishable from that of the int constant, decimal 65.

The upshot of this is that small int values may be stored in char variables, and char values may he stored in int variables! Character variables are therefore signed quantities restricted to the range [-128, 127]. However, it is a requirement of the language that the decimal equivalent of each of the printing characters be non-negative.

We are assured then that in any C implementation in which a char is stored in an 8-bit byte, the corresponding int value will always be a non-negative quantity, whatever the value of the leftmost (sign) bit may be. Now, identical bit patterns within a byte may be treated as a negative quantity by one machine, as a positive by another. For ensuring portability of programs which store non-character data in char variables the unsigned char declaration is useful: it changes the range of chars to [0, 255].

[Note :However, the ANSI extension signed char explicitly declares a signed character type to override, if need be, a possible default representation of unsigned chars.]

One consequence of the fact that C does not distinguish between the internal representation of byte-sized ints and chars is that arithmetic operations which are allowed on ints are also allowed on chars! Thus in C, if you wish to, you may multiply one character value by another.

Here are some variables declared as chars, and defined as escape sequences:

char newline = '\n',
char single_quote = '\"';

Character constants can also be defined via their octal ASCII codes. The octal value of the character is preceded by a backslash, and is enclosed in single quotes:

char terminal_bell = '\07';
/* 7 = octal ASCII code for beep */

char backspace = '\010';
/ *10 = octal code for backspace */

[Note: For ANSI C Compilers character constants may be defined by hex digits instead of octals. Hex digits are preceded by x, unlike 0 in the case of octals. Thus in ANSI C:

char backspace =\x A';

is an acceptable alternative declaration to

char backspace = '\010';

Any number of digits may be written, but the value stored is undefined if the resulting character value exceeds the limit of char.]

On an ASCII machine both '\b' and '\010' are equivalent representations. Each will print the backspace character. But the latter form, the ASCII octal equivalent of '\b', will not work on an EBCDIC machine, typically an IBM mainframe, where the collating sequence of the characters (i.e., their gradation or numerical ordering) is different. In the interests of portability therefore it is preferable to write '\b' for the backspace character, rather than its octal code. Then your program will work as certifiably on an EBCDIC machine as it will on an ASCII.

Note that the character constant 'a' is not the same as the string "a". (We will learn later that a string is really an array of characters, a bunch of characters stored in consecutive memory locations, the last location containing the null character; so the string "a" really contains two chars, 'a' immediately followed by '\0'). It is important to realise that the null character is not the same as the decimal digit 0, the ASCII code of which is 00110000.

Just as %d in printf () or scanf () allows us to print and read ints, %c enables the input and output of single characters which are the values of char variables. Let's look at Programs 2. 10 and 2.11 below:

/* Program 1 */ 
#include <stdio.h>
main ( )
{ 
char a = 'H', b = 'e', c 'I', d 'o', newline '\n';
printf ("%c", a); 
printf ("%c", b); 
printf ("%c", c); 
printf ("%c", c); 
printf ("%c", d); 
printf ("%c", newline); 
}

The output of Program 1 is easily predictable (what is it?).

/* Program 2 */ 
#include <stdio.h>
main ( )
{ 
char val_1, val_2; 
int vai_3; 
printf ("Press any of the keys a - z, then press \n"); 
scanf ("%c", &val_1); 
printf ("Press another key in a - z, then press \n"); 
scanf ("%c", &val_2); 
printf ("Assuming you're working on an ASCII machine, \nthe chars that you typed have decimal equivalents %d and %d, respectively", val_1, val_2); 
val_3 = val_1 * val_2; 
printf ("Their product is %d\n", val_3); 
}

Execute the above program to verify that char variables behave like one byte ints in arithmetic operations.

The %c format conversion character in a printf () outputs escape sequences, as you saw in Program 2. Execute Program 3 if you want a little music:

/* Program 3 */ 

#include <stdio.h> 
main ( )
{ 
char bell = '\007'; /* octal code of the terminal bell */ 
char x = 'Y', y = 'E', z = 'S', exclam = '!'; 
printf ("Do you hear the bell ? %c%c%c%c%c%c%c", bell, x, bell, y, bell, z, exclam); 
}

Program 4 assigns a character value to an int variable, an integer value to a char variable, and performs a computation involving these variables. Predict the output of the program, and verify your result by executing it

/* Program 4 */ 
#include <stdio.h> 
main ( )
{ 
int alpha = 'A', beta; 
char gamma = 122; beta = gamma - alpha; 
printf ("beta seen as an int is: %d\n", beta); 
printf ("beta seen as a char is: %c\n", beta); 
}

End-0f-File (EOF) character

One character that is often required to be sensed in C programs is not strictly speaking a character at all: it's the EOF or End-0f-File character, and its occurrence indicates to a program that the end of terminal or file input has been reached. Because the EOF is not a character, being outside the range of chars, any program that's written to sense it must declare an int variable to store character values. As we see in Program 2.13, this is always possible to do. An int variable can accommodate all the characters assigned to it, and can also accommodate EOF. We'll see uses for EOF in later units.

The putcular ( )function (pronounced "put character"), which takes a character variable or constant as its sole argument, is often a more convenient alternative for screen output thin is the printf ( ) When this function is invoked (for which purpose you may need to #include stdio.h), the character equivalent of its argument is output on the terminal, at the current position of the cursor:

putchar (char_var);

Suppose char_var has been assigned the value 'A'. Then 'A' will be displayed where the cursor was.

Reciprocally, getchar ( ) pronounced "get character") gets a single character from the keyboard, and can assign it to a char variable. (stdio.h 'may have to be #included before getchar ( )can be used.) It has no arguments, and is typically invoked in the following way:

char_var = getchar ( );

When such a statement is encountered, the execution of the program is stayed until a key is pressed. Then char_var is assigned the character value of the key that was pressed.

Program 5 below illustrates the usage of these functions. Your compiler may require the inclusion of stdio.h to invoke getchar ( ) and putchar ( ).

/* Program 5 */ 
#include <stdio.h> 
main ( )
{ 
char key_pressed; 
printf ("Type in a lowercase letter (a - z), press :"); 
key_pressed = getchar ( ); /* get char from keyboard*/ 
printf ("You pressed"); 
putchar (key_pressed - 32); /* put upperease char on Terminal*/ 
putchar ('\n');

/* this program converts to uppercase because ASCII decimal equivalent is 32 less than for the corresponding lower case character. */
}

Saturday, July 7, 2012

Range Modifiers for Integer Variables in C

On occasions you may need to work with strictly non-negative integers, or with integers in a shorter or longer interval than the default for ints. The following types of range modifying declarations are possible:

(I) unsigned

usage: unsigned int stadium_seats;

This declaration "liberates" the sign bit, and makes the entire word (including the freed sign bit) available for the storage of non-negative integers. [Note: The sign bit_the leftmost bit of a memory word _ determines the sign of the contents of the word when it's set to 1, the value stored in the remaining bits is negative. Most architectures use two's complement arith- metic, in which the sign bit is "weighted", i.e. it has an associated place value which is nega- tive. Thus on a 16-bit machine its value is -215, or -32,768. So a 16-bit signed number such as 10000000 00111111 would have the value 20 + 21 + 22+ 23 +24 + 25 -215 = -32,705. As an unsigned integer this string of bits would have the value 32831.] On PCs the unsigned decla- ration allows for int variables the range [0, 65535] and is useful when one deals with quan- tities which are known beforehand to be both large and non-negative, e.g. memory addresses, a stadium's seating capacity, etc.

Just as %d in-the printf ( ) prints decimal int values, %u is used to output unsigned ints, as the program below illustrates. Execute the program and determine its output also examine the effect changing the % u format conversion specifiers to %d in the printf Os. Can you explain your results?

#include <stdio.h> 
main()
{
    unsigned int stadium_seats, tickets_sold, standing_viewers;
    stadium_seats = 40000;
    tickets_sold = 50000;
    standing_viewers = tickets_sold - stadium_seats;
    printf ("Tickets sold: %u\n", tickets_sold);
    printf ("Scats available: %u\n", stidium_scats);
    printf ("There could be a stajnpede because\,n");
    printf ("there may be nearly %u standees at the match.\n", standing_viewers);
}

(II) short
usage: short int friends;

The short int declaration may be useful in instances where an integer variable is known beforehand to be small. The declaration above ensures that the range of friends will not ex- ceed that of ints, but on some computers the range may be shorter (e.g. -128 through 127) friends may be accommodated in a byte, thus saving memory. There.was a time in the olden days of computing,,when main memory was an expensive resource, that programmers tried by such declarations and other stratagems to optimise core usage to the extent possible. (The VAX computer uses two bytes to store short ints, half the amount it uses for ints but for present-day PCs, with memory cheap and plentiful, most compiler writers make no distnc- tion between ints and short ints.)

The %d specification in the printf ( ) is also used to output short ints.

(III) unsigned short
usage: unsigned short int books

The range of books will not exceed that of unsigned ints it may be shorter.

(IV) long
usage: long int stars_in_galaxy;

This declaration is required when you need to use integers larger than the default for ints. On most computers long ints are 4-byte integers ranging over the interval [-2147483648, 2147483647]. When a long integer constant is assigned a value the letter L (or I) must be written immediately after the rightmost digit: long int big_num = 123456789OL;

% ld in the printf 0 outputs long decimal ints, as you may verify by executing

#include <stdio.h> 
main ( )
{
    long int population-2000 = 123456789OL;
    printf ("The population of this country in 2000 AD\,n");
    printf ("will exceed %Id if we do\n", populaton_2000);
    printf ("not take remedial steps now.\n");
}


(V) unsigned long
usage: unsigned long int population_2000

The unsigned long declaration transforms the range of long ints to the set of 4-byte non- negative integers. Here population_2000 is allowed to range over [0, 4294967295] (Let's hope that larger-sized words will not be required to store this value!) unsigned longs are output by the %lu format conversion specifier in the printf 0.

In the above declarations shorter forms are allowed: thus you may write:
unsigned letters; /* instead of unsigned int letters*/
long rope; /* insted of long int rope*/
unsigned short note; /* instead of unsigned short int note*/ etc.

Integer Data Types in C Programming Language

C program variables and constants are of four types: char, int, float and double. Before an identifier can be used in a C program its type must be explicitly declared. Here's a declaratory statement of C:

int apples;

This statement declares the programmer's intent that apples will store a signed integer value, i.e. apples may be either a positive or a negative integer within the range set for variables of type int. Now this range can be very much machine dependent; it depends, among other things on the word size of your machine. For most compilers for the IBM PC ints are stored in two consecutive bytes, and are restricted to the range [-32768, 32767]. Compare this with the VAX or the Macintosh, where ints are,4-byte signed integers in the range [-2147483648, 2147483647]. In declaring apples to be an int you are telling the compiler how much space to allocate for its storage. You have also made an assumption of the range in which you expect its value to lie.

In contrast to Pascal, in C it is possible and in fact usual to both declare a variable's type and, where needed, define its value in the same statement:

int salary = 5000;

It is not correct to assume that a variable which has only been declared e.g.:

int volts;
/* volts is unpredictable */

but has not been defined, i.e. assigned a value, automatically gets the value 0. In fact its value may be anything but 0! Note that the thousands, millions or billions place values are never separated by commas, when constants are defined in C programs.

Let's 1(x)k at Program 2.1, and its output. The program adds two ints x and y, and prints their sum, z. Don't worry if you can't understand everything about the program just yet. Only remember that the printf () can be. used to print numbers just as easily as it prints strings. To print an int x the following printf () will do:

printf ("The value of x is: %d\n", x);

The %d signifies that x is to be printed as a decimal integer.

#include <stdio.h>
main()
{ 
int x = 5, y = 7, z; 
z = x + y; 
printf ("The value of x is: %d\n", x); 
printf ("The value of y is: %d\n", y); 
printf ("Their sum, z, is: %d\n", z); 
}

The output of Program is appended below.
The value of x is: 5
The value of y is: 7
Their sum, z, is: 12

To understand the very great importance of using variables in a computation only after having assigned them values, execute the following program and determine its output on your computer:


#include <stdio.h>
main()
{
int x, y, z; /* x, y and z are undefined. */ /* contd. */
z = x + y ; 
printf ("The value of x is: %d\n", x); 
printf ("The value of y is: %d\n", y); 
printf ("Their sum, z, is: %d\n", z);
}
On our machine, a VAX 11/780 from Digital Equipment Corporation, U.S.A. the output was:

The value of x is: 2146744409 The value of y is: 2146744417 Their sum, z, is: -1478470

Now, looking at the output of this program, could you possibly have predicted the values x, y and z would get? Moral: Never assume a variable has a meaningful value, unless you give it one.