1 / 41

Numeric Arrays

Numeric Arrays. Numeric Arrays. Chapter 4. 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.

Télécharger la présentation

Numeric Arrays

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

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[10]; 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 • [10] 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[10] = {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 ([5]) 9054 ([2]) 9070 9053 ([1]) 9064 ([7]) 9052 ([1]) 9055 ([2]) 9050 ([0]) 9072 9071 9056 ([3]) 9069 ([9]) 9051 ([0]) 9057 ([3]) 9068 ([9]) 9058 ([4]) 9059 ([4]) 9067 ([8]) 9060 ([5]) 9073 9066 ([8]) 9062 ([6]) 9063 ([6]) 9065 ([7]) 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[0] 9052 & 9053numvector[1] 9050 & 9051numvector[0] 9050 & 9051numvector[0] 9052 & 9053numvector[1] 9052 & 9053numvector[1] 9050 & 9051numvector[0] 9052 & 9053numvector[1] 9054 & 9055numvector[2] 9054 & 9055numvector[2] 9054 & 9055numvector[2] 9054 & 9055numvector[2] 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 [0]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[3] 9058 & 9059 numvector[4] 9060 & 9061 numvector[5] 9054 & 9055 numvector[2] 9052 & 9053 numvector[1] 9072 & 9073 9050 & 9051 numvector[0] 9068 & 9069 numvector[9] 9070 & 9071 ---- 81 0 1 4 ---- 25 9 16 9062 & 9063 numvector[6] 9064 & 9065 numvector[7] 9066 & 9067 numvector[8] 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[6] 12348 to 12351 fvector[0] 12352 to 12355 fvector[1] 12380 to 12383 fvector[8] 12376 to 12379 fvector[7] 12356 to 12359 fvector[2] 12372 to 12375 fvector[6] 12368 to 12371 fvector[5] 12360 to 12363 fvector[3] 12364 to 12367 fvector[4] ----- ----- ----- ----- ----- ----- ----- ----- ----- ----- Suppose we made the declaration: floatfvector[10]; 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

  13. Consider the following C Code: #include <stdio.h> void main() { int vector[] = {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}; int index; printf("the base address of vector is %lu\n",&vector); for (index = 0; index < 10; index++) printf("vector[%d] = %d; stored at address %lu\n", index, vector[index], &vector[index]); } Numeric Arrays The (slightly modified) output would be: the base address of vector is 41553194 vector[0] = 0; stored at address 41553194 vector[1] = 1; stored at address 41553196 vector[2] = 4; stored at address 41553198 vector[3] = 9; stored at address 41553200 vector[4] = 16; stored at address 41553202 vector[5] = 25; stored at address 41553204 vector[6] = 36; stored at address 41553206 vector[7] = 49; stored at address 41553208 vector[8] = 64; stored at address 41553210 vector[9] = 81; stored at address 41553212

  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[8] = 64; stored at address 41553210 vector[9] = 81; stored at address 41553212 vector[10] = -13107; stored at address 41553214 vector[11] = -15863; stored at address 41553216

  15. How can there be a vector[10]? Or vector[11]?? Numeric Arrays • vector[10] is nothing more than address 10 * 2 = 20 bytes offset from the base (41553194 + 20 = 41553114) • vector[11] 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[10], -13107 ???

  16. 4155314 4155315 11001100 11001101 If we were to go to address: &vector[10] 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[10] = {0, 1, 4, 9, 16, 25, 36, 49, 64, 81}, vect2[10] = {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[0] = 12350 AND vect2 = &vect2[0] = 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[0] = 12350 Where: AND vect2 = &vect2[0] = 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[10][2], index; for (index = 0; index < 10; index++) { matrix[index][0] = index * index; matrix[index][1] = 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[9][0] matrix[8][0] matrix[8][1] matrix[7][1] matrix[2][0] matrix[0][0] matrix[1][1] matrix[1][0] matrix[0][0] matrix[3][0] matrix[3][1] matrix[4][0] matrix[2][1] matrix[4][1] matrix[9][1] matrix[7][0] matrix[5][1] matrix[5][0] matrix[6][1] matrix[6][0] 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[2][0] matrix[3][1] matrix[4][1] matrix[4][0] matrix[3][0] matrix[2][1] matrix[1][0] matrix[7][1] matrix[0][0] matrix[1][1] matrix[9][1] matrix[9][0] matrix[8][1] matrix[8][0] matrix[0][1] matrix[7][0] matrix[6][1] matrix[5][0] matrix[6][0] matrix[5][1] Row/Col Address Row/Col Address [0][0] 63128 + 0*4 + 0*2 = 63128 [5][0] 63128 + 5*4 + 0*2 = 63148 Numeric Arrays [0][1] 63128 + 0*4 + 1*2 = 63130 [5][1] 63128 + 5*4 + 1*2 = 63150 [1][0] 63128 + 1*4 + 0*2 = 63132 [6][0] 63128 + 6*4 + 0*2 = 63152 [1][1] 63128 + 1*4 + 1*2 = 63134 [6][1] 63128 + 6*4 + 1*2 = 63154 [2][0] 63128 + 2*4 + 0*2 = 63136 [7][0] 63128 + 7*4 + 0*2 = 63156 [2][1] 63128 + 2*4 + 1*2 = 63138 [7][1] 63128 + 7*4 + 1*2 = 63158 [3][0] 63128 + 3*4 + 0*2 = 63140 [8][0] 63128 + 8*4 + 0*2 = 63160 [3][1] 63128 + 3*4 + 1*2 = 63142 [8][1] 63128 + 8*4 + 1*2 = 63162 [4][0] 63128 + 4*4 + 0*2 = 63144 [9][0] 63128 + 9*4 + 0*2 = 63164 [4][1] 63128 + 4*4 + 1*2 = 63146 [9][1] 63128 + 9*4 + 1*2 = 63166

  26. The formula works regardless of how many dimensions there are. Numeric Arrays Consider the C declaration: floatmultiarray[5][4][3][2]; 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[0][0][2][1] 21578 + 0*96 + 0*24 + 2*8 + 1*4 = 21598 multiarray[1][2][0][0] 21578 + 1*96 + 2*24 + 0*8 + 0*4 = 21722 multiarray[1][3][2][1] 21578 + 1*96 + 3*24 + 2*8 + 1*4 = 21915 21578 + 2*96 + 1*24 + 1*8 + 0*4 = 21802 multiarray[2][1][1][0] 21578 + 4*96 + 3*24 + 2*8 + 1*4 = 22054 multiarray[4][3][2][1]

  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[10] = {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[10] = {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[10] = {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[10] = {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[10] = {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[10] = {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[9]) && (* index != 25)) index++; if (index > &vector[9]) 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[9]) && (*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[9] ? (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[9] 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[9] ? (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[100], index; • External Arrays • Known to ALL functions • Do NOT Expire when a particular functions ends • INITIALIZED when declared intintarray[100]; 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[100]; intindex;

  41. Numeric Arrays

More Related