 Download Download Presentation Numeric Arrays

# Numeric Arrays

Download Presentation ## Numeric Arrays

- - - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - - -
##### Presentation Transcript

1. Numeric Arrays Numeric Arrays Chapter 4

2. What you MUST know before we start: Numeric Arrays (Remember: The topics in this course build on each other) • What integers and real numbers are • How integers and real numbers are stored in RAM • The basic concept of what an address is and how it is used • The use of C/C++ to manipulate integers and real numbers

3. Numeric Arrays • Array: (def) A Regular Order or Arrangement Numeric Arrays • For our Purposes, we can define an array as a data structure containing a fixed number of contiguous storage elements all of the same type Assume we wished to store the squares of the numbers: Number: 0 1 2 3 4 5 6 7 8 9 Square: 25 0 1 4 9 16 36 49 64 81 We could store the numbers as scalar variables: intd0 = 0,d1 = 1,d2 = 4,d3 = 9,d4= 16,d5 = 25, d6 = 36,d7 = 49,d8 = 64,d9 = 81;

4. The problem with this approach is: Numeric Arrays • Remembering the variables names can become complex • Manipulating each of the variables is tedious For Example, suppose we were trying to find the value 64 in our list, but didn’t know where it was stored: if (d0 == 64) printf(“at d0’’); else if (d1 == 64) printf(“at d1’’); else if (d2 == 64) printf(“at d2’’); else if (d3 == 64) printf(“at d3’’); else if (d4 == 64) printf(“at d4’’); else if (d5 == 64) printf(“at d5’’); else if (d6 == 64) printf(“at d6’’); else if (d7 == 64) printf(“at d7’’); else if (d8 == 64) printf(“at d8’’); else if (d9 == 64) printf(“at d9’’); else printf(“Not found”);

5. A preferred alternative would be to store the squares of the numbers as an integer array: Numeric Arrays intnumvector; What does this declaration do ??? • Using the datatype int implies that we will require 2-bytes per element • the variable name numvector will be associated with the base address of the array •  indicates how many elements will be in our array • since we are creating an array of type int, we are requesting 2 * 10 = 20 CONTINGUOUS bytes of RAM

6. We could also initialize our array when we declare it: intnumvector = {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}; Numeric Arrays OR intnumvector[] = {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}; Even though we do not explicitly indicate how many elements are in the array, we are still requesting 20 bytes of CONTIGUOUS storage (We are just asking the compiler to determine the number) Because we are specifying only one subscript or offset, we are declaring a vector (a one-dimensional array)

7. 9061 () 9054 () 9070 9053 () 9064 () 9052 () 9055 () 9050 () 9072 9071 9056 () 9069 () 9051 () 9057 () 9068 () 9058 () 9059 () 9067 () 9060 () 9073 9066 () 9062 () 9063 () 9065 () 00000000 00000000 00000100 00001001 00000000 00000000 00000000 00011001 00000000 00000001 0001000 00000000 00000000 00000000 00100100 00010111 01010001 01000000 01101001 00110001 00000000 11001000 01110001 00000000 How are arrays stored in RAM ??? • That depends of the type of data we wish to store • In our case, we are storing an integer array containing 10 elements, so we are requesting 2 * 10 = 20 bytes of CONTIGUOUS storage • If (at run-time) we find there are 20 contiguous bytes of storage available starting at location 9050: Numeric Arrays

8. 9050 & 9051numvector 9052 & 9053numvector 9050 & 9051numvector 9050 & 9051numvector 9052 & 9053numvector 9052 & 9053numvector 9050 & 9051numvector 9052 & 9053numvector 9054 & 9055numvector 9054 & 9055numvector 9054 & 9055numvector 9054 & 9055numvector 0 1 0 1 0 1 0 1 4 4 4 4 At a more abstract, and understandable, level, this might appear as: Numeric Arrays • Notice: • The first element on the list (element number 1) has the subscript (offset) 0 (zero) • The last element on the list (element number 10) has the subscript (offset) 9 (nine).

9. Why is the first element subscripted as AND why is it also referred to as the offset ??? Numeric Arrays In fact, the subscript (at least in C) IS the offset from the base address of the array • REMEMBER: When we first initialized our array, we stated: • The variable name numvector will be associated with the base address of the array • Given a base address, we can use the offset (or subscript) to determine the addresses of any individual element in the array How does this work ???

10. Remember: Our basic directive: Numeric Arrays “Give me an address and tell me what type ofdata is stored there, and I will tell you the value of that data type” Arrays allow a convenient way of determining an address Given an integer array of 10 elements, we can calculate individual array addresses using the formula: Element address = base address of the array + (offset number * 2) (Since 2-bytes are needed for an integer)

11. 9056 & 9057 numvector 9058 & 9059 numvector 9060 & 9061 numvector 9054 & 9055 numvector 9052 & 9053 numvector 9072 & 9073 9050 & 9051 numvector 9068 & 9069 numvector 9070 & 9071 ---- 81 0 1 4 ---- 25 9 16 9062 & 9063 numvector 9064 & 9065 numvector 9066 & 9067 numvector 36 49 64 Given our the Array (as stored in RAM): Numeric Arrays We can calculate element addresses as: Address: Offset Address: Offset 0 9050 + (0 * 2) = 9050 5 9050 + (5 * 2) = 9060 1 9050 + (1 * 2) = 9052 6 9050 + (6 * 2) = 9062 2 9050 + (2 * 2) = 9054 7 9050 + (7 * 2) = 9064 3 9050 + (3 * 2) = 9056 8 9050 + (8 * 2) = 9066 4 9050 + (0 * 2) = 9058 9 9050 + (9 * 2) = 9068

12. 12372 to 12375 fvector 12348 to 12351 fvector 12352 to 12355 fvector 12380 to 12383 fvector 12376 to 12379 fvector 12356 to 12359 fvector 12372 to 12375 fvector 12368 to 12371 fvector 12360 to 12363 fvector 12364 to 12367 fvector ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Suppose we made the declaration: floatfvector; And the base address of the array was 12348 Numeric Arrays In RAM this might appear as: We could calculate element addresses as: Offset Address: Offset Address: 0 12348 + (0 * 4) = 12348 5 12348 + (5 * 4) = 12368 1 12348 + (1 * 4) = 12352 6 12348 + (6 * 4) = 12372 2 12348 + (2 * 4) = 12356 7 12348 + (7 * 4) = 12376 3 12348 + (3 * 4) = 12360 8 12348 + (8 * 4) = 12380 4 12348 + (4 * 4) = 12364 9 12348 + (9 * 4) = 12384

14. What if we entered illegal subscripts? For example, for the previous code, what if we entered the for loop parameters: Numeric Arrays for (index = 8; index < 12; index++) printf ("vector[%d] = %d; stored at address %lu\n", index, vector[index], &vector[index]); (This is illegal because index should not take on any values larger than 9) The (slightly modified) output might appear as: vector = 64; stored at address 41553210 vector = 81; stored at address 41553212 vector = -13107; stored at address 41553214 vector = -15863; stored at address 41553216

15. How can there be a vector? Or vector?? Numeric Arrays • vector is nothing more than address 10 * 2 = 20 bytes offset from the base (41553194 + 20 = 41553114) • vector is nothing more than address 11 * 2 = 22 bytes offset from the base (41553194 + 22 = 41553116) index++ The command we issued was: Which increments the contents of index (at the time, 9) by 1 &vector[index] Therefore, the location: Would yield the addresses given above But why is the value stored at, for example, vector, -13107 ???

16. 4155314 4155315 11001100 11001101 If we were to go to address: &vector Numeric Arrays We might find 41553114 which equates to Neg. 011001100110010 One’s Compliment + 1 011001100110011 Two’s Compliment = -(213 + 212 + 29 + 28 + 25 + 24 + 21 + 20) = -(8192 + 4096 + 512 + 256 + 32 + 16 + 2 + 1) = -13,107

17. Multi-dimensional Arrays Suppose I wished to store the Squares AND the cubes of the digits from 0 through 9 Numeric Arrays We could store them as two vectors: intvect1 = {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}, vect2 = {0, 1, 8, 27, 64, 125, 216, 343, 512, 729}; Assuming that we did, AND we found that the base addresses of the two arrays were: vect1 = &vect1 = 12350 AND vect2 = &vect2 = 12424 the relevant section of RAM might appear as:

18. 12424 & 12425 12354 & 12355 12356 & 12357 12352 & 12353 12358 & 12359 12350 & 12351 12368 & 12369 12362 & 12363 12364 & 12365 12366 & 12367 12360 & 12361 12442 & 12443 12426 & 12427 12428 & 12429 12430 & 12431 12432 & 12433 12434 & 12435 12436 & 12437 12438 & 12439 12440 & 12441 9 729 81 64 512 49 8 0 16 1 216 4 27 1 64 125 0 343 36 25 Numeric Arrays . . . . . . . . . . . . . . . . vect1 = &vect1 = 12350 Where: AND vect2 = &vect2 = 12424

19. OR we could store the values as ONE table: Table sqrscubes Numeric Arrays Row\Col 0 0 0 0 0 1 1 1 Where: 2 4 8 The Row and Column numbers are the table offsets 3 9 27 4 16 64 5 25 125 6 36 217 7 49 343 64 512 8 81 729 9

20. What difference does it make if we use one or two arrays ??? Numeric Arrays • With two vectors we need 2 blocks of RAM each containing 20 contiguous bytes of RAM • With one array (matrix) we need 1 block of RAM which contains 40 contiguous bytes • With two vectors we need two variables (two baseaddresses) • With one matrix we need one variable (one baseaddress) • The ORDER in which the data is stored in RAM differs How is RAM storage different ???

21. Consider the following C code: void main() { intmatrix, index; for (index = 0; index < 10; index++) { matrix[index] = index * index; matrix[index] = index * index * index; } } Numeric Arrays • Using the datatype int implies that we will require 2-bytes per element • since we are creating a 2-dimensional array of type int, we are requesting 2 * 2 * 10 = 40 CONTINGUOUS bytes of RAM • the variable name matrix will be associated with the base address of the array

22. 63146 & 63147 63130 & 63131 63132 & 63133 63128 & 63129 63166 & 63167 63134 & 63135 63144 & 63145 63138 & 63139 63140 & 63141 63142 & 63143 63136 & 63137 63148 & 63149 63150 & 63151 63152 & 63153 63154 & 63155 63156 & 63157 63158 & 53159 63160 & 63161 63162 & 63163 63164 & 63165 16 1 27 9 81 8 4 729 1 64 343 0 125 36 0 217 49 64 512 25 If the base address for the array matrix was: 63128 Numeric Arrays The relevant portion of RAM might appear as: NOTICE that the data is stored BY ROWS or by rowoffset

23. 63166 & 63167 63164 & 63165 63162 & 63163 63160 & 63161 63158 & 53159 63130 & 63131 63134 & 63135 63136 & 63137 63128 & 63129 63138 & 63139 63146 & 63147 63140 & 63141 63144 & 63145 63132 & 63133 63148 & 63149 63150 & 63151 63152 & 63153 63154 & 63155 63156 & 63157 63142 & 63143 matrix matrix matrix matrix matrix matrix matrix matrix matrix matrix matrix matrix matrix matrix matrix matrix matrix matrix matrix matrix Looking at RAM in terms of offsets, we find: Numeric Arrays Which corresponds to the manner in which we originally laid out our table. How do we calculate these addresses ???

24. Since we know that each row contains 2 elements (4-bytes), and each element requires 2-bytes of storage, we must (slightly) modify our previous formula: Numeric Arrays Element address = base address of the array + (rowoffset * bytes per row) + (column offset * bytes per element) Since we are dealing with an integer array which has the base address 63128 the formula is: Element address = 63128 + (rowoffset * 4) + (column offset * 2)

25. 63136 & 63137 63146 & 63147 63128 & 63129 63144 & 63145 63130 & 63131 63132 & 63133 63142 & 63143 63134 & 63135 63140 & 63141 63138 & 63139 63150 & 63151 63160 & 63161 63166 & 63167 63164 & 63165 63162 & 63163 63148 & 63149 63158 & 63159 63156 & 63157 63154 & 63155 63152 & 63153 matrix matrix matrix matrix matrix matrix matrix matrix matrix matrix matrix matrix matrix matrix matrix matrix matrix matrix matrix matrix Row/Col Address Row/Col Address  63128 + 0*4 + 0*2 = 63128  63128 + 5*4 + 0*2 = 63148 Numeric Arrays  63128 + 0*4 + 1*2 = 63130  63128 + 5*4 + 1*2 = 63150  63128 + 1*4 + 0*2 = 63132  63128 + 6*4 + 0*2 = 63152  63128 + 1*4 + 1*2 = 63134  63128 + 6*4 + 1*2 = 63154  63128 + 2*4 + 0*2 = 63136  63128 + 7*4 + 0*2 = 63156  63128 + 2*4 + 1*2 = 63138  63128 + 7*4 + 1*2 = 63158  63128 + 3*4 + 0*2 = 63140  63128 + 8*4 + 0*2 = 63160  63128 + 3*4 + 1*2 = 63142  63128 + 8*4 + 1*2 = 63162  63128 + 4*4 + 0*2 = 63144  63128 + 9*4 + 0*2 = 63164  63128 + 4*4 + 1*2 = 63146  63128 + 9*4 + 1*2 = 63166

26. The formula works regardless of how many dimensions there are. Numeric Arrays Consider the C declaration: floatmultiarray; We are requesting a total of: 4 * (5 * 4 * 3 * 2) = 4 * 120 = 480 Contiguous bytes of RAM Notice that: • Each change in the last (4th) offset requires: 4-bytes • Each change in the 3rd offset requires: 8-bytes • Each change in the 2nd offset requires: 24-bytes • Each change in the 1st offset requires: 96-bytes Which makes sense since the first offset can change 5 times and we know we require a total of 480 (= 5 * 96) bytes

27. The General formula, therefore, would be: Element address = base address of the array Numeric Arrays + (firstoffset * 96) + (secondoffset * 24) + (thirdoffset * 8) + (fourthoffset * 4) If we found that the base address of our variable multiarray was: 21578 We could calculate the following (sample) addresses as: Array Element Address multiarray 21578 + 0*96 + 0*24 + 2*8 + 1*4 = 21598 multiarray 21578 + 1*96 + 2*24 + 0*8 + 0*4 = 21722 multiarray 21578 + 1*96 + 3*24 + 2*8 + 1*4 = 21915 21578 + 2*96 + 1*24 + 1*8 + 0*4 = 21802 multiarray 21578 + 4*96 + 3*24 + 2*8 + 1*4 = 22054 multiarray

28. Searching an Array Numeric Arrays Assume that we wished to determine if the number 25 was in our original list (of squared values): #include <stdio.h> void main() { intvector = {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}; intindex; for (index = 0; index < 10 && vector[index] != 25; index++); if (index > 9) printf(“The value was not found\n”); else printf(“The value %d was found at offset %d\n”, vector[index], index); } Let’s Consider this program line by line

29. 12354 & 12355 12362 & 12363 12368 & 12369 12360 & 12361 12366 & 12367 12350 & 12351 12352 & 12353 12358 & 12359 12364 & 12365 15234 & 15235 12356 & 12357 49 4 81 64 0 9 16 25 36 1 intvector = {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}; Reserve (& initialize) 2 * 10 = 20 bytes at base address vector Numeric Arrays intindex; Reserve 2 bytes at base address index for (index = 0; Set (once) the contents of location index to zero (0) 0

30. 12360 & 12361 12364 & 12365 12362 & 12363 12358 & 12359 12356 & 12357 12354 & 12355 12352 & 12353 12366 & 12367 12350 & 12351 12368 & 12369 15234 & 15235 4 0 36 25 64 9 81 49 1 16 intvector = {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}; Reserve (& initialize) 2 * 10 = 20 bytes at base address vector Numeric Arrays intindex; Reserve 2 bytes at base address index for (index = 0; index < 10 && vector[index] != 25; True True 0 Therefore, execute the command

31. intvector = {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}; Reserve (& initialize) 2 * 10 = 20 bytes at base address vector Numeric Arrays intindex; Reserve 2 bytes at base address index for (index = 0; index < 10 && vector[index] != 25; index++); What Command ??? • There is none needed in this case • We know that the element we are looking for has not been found (vector[index] != 25) • We also know that the list hasn’t been exhausted (index < 10) • We need only move to the next element

32. intvector = {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}; Reserve (& initialize) 2 * 10 = 20 bytes at base address vector Numeric Arrays intindex; Reserve 2 bytes at base address index for (index = 0; index < 10 && vector[index] != 25; index++); Throughout the loop, the logic would be: (contents of) index Vector[index] != 25 ? index <= 10 ? Pass No. (= 0) Yes Yes 0 1 1 Yes (= 1) Yes 2 2 Yes (= 4) Yes 3 (= 9) Yes 3 Yes 4 4 Yes (= 16) Yes 5 5 Yes (= 25) NO 6 We are out of the loop

33. intvector = {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}; Reserve (& initialize) 2 * 10 = 20 bytes at base address vector Numeric Arrays intindex; Reserve 2 bytes at base address index for (index = 0; index < 10 && vector[index] != 25; index++); Once out of the loop we need to print our findings: False if (index > 9) º º º º º º º º º º else printf(“The value %d was found at offset %d\n”, vector[index], index); The value 25 was found at offset5

34. Pointers and Arrays: Numeric Arrays Assume that we wished to determine if the number 25 was in our original list (of squared values): #include <stdio.h> void main() { intvector[] = {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}; int * index; index = vector; while ((index <= &vector) && (* index != 25)) index++; if (index > &vector) printf(“The value was not found\n”); else printf(“The value %d was found at address %p\n”, *index, index); } Let’s Consider this program line by line

35. intvector[] = {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}; Reserve (& initialize) 2 * 10 = 20 bytes at base address vector Numeric Arrays (assume that vector has the base address 8900) int *index; Reserve 4-bytes of storage at location index If we go to location index, we would find a signed integer value (assume that index has the base address 8932) index = vector; Store the address of vector (i.e., 8900) at location index while ((index <= &vector) && (*index != 25)) Continue processing as long as: • The contents of index (presently 8900) is less than or equal to &vector (= 8900 + 9*2 = 8918) AND • The contents of the address stored at location index (at location 8900 we will presently find the integer 0) is not equal to the integer 25

36. Inside the loop, there is only one statement: index++; Numeric Arrays • Increment the contents of location index • since location index contains an address which points to an integer, incrementing means increasing the value by 2 Throughout the loop, the logic would be: = 8918 index <= &vector ? (contents of) index *index != 25 ? *index Pass No. Yes 8900 0 Yes 1 8902 Yes 1 Yes 2 8904 Yes 4 Yes 3 8906 Yes 9 Yes 4 8908 Yes 16 Yes 5 8910 Yes 25 NO 6 We are out of the loop

37. When we come out of the loop, there are two possibilities: Numeric Arrays EITHER: index > &vector Meaning that the contents of location index (which contains an an address) are greater than the address of the last legal array address (i.e., 8918) In which case we print out: The value was not found OR We print out the value: The value 25 was found at address 8910 (Assuming we were looking for the value 25) How could the contents of location index ever be greater than the array address 8918 ???

38. If we were looking for the value 108 (not on the list): = 8918 Numeric Arrays index <= &vector ? (contents of) index *index *index != 108 ? Pass No. 8900 Yes 0 Yes 1 8902 Yes 1 Yes 2 8904 Yes 4 Yes 3 9 8906 Yes Yes 4 Yes 16 Yes 8908 5 Yes 25 Yes 8910 6 Yes 36 Yes 8912 7 Yes 49 Yes 8914 8 64 Yes 8916 Yes 9 81 8918 Yes Yes 10 8920 NO Unknown 11 Probably Not And we are out of the loop

39. Array Declarations • Automatic Arrays • Defined INSIDE a function • Exists ONLY for the duration of the function • NOT initialized • When done, memory allocation freed Numeric Arrays intmain() { intintarray, index; • External Arrays • Known to ALL functions • Do NOT Expire when a particular functions ends • INITIALIZED when declared intintarray; intmain() { intindex;

40. Static Arrays Numeric Arrays • Like Automatic Arrays, LOCAL to the function • Like External arrays, RETAIN VALUES between calls • INITIALIZED at declaration intmain() { staticintintarray; intindex;

41. Numeric Arrays