-
Notifications
You must be signed in to change notification settings - Fork 2
/
Vector.java
266 lines (238 loc) · 7.27 KB
/
Vector.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
import java.util.LinkedList;
/**
* Representation of a vector
*
* @author Siddarth Senthilkumar
* @version 1.0
*/
public class Vector {
private double[] vector;
/**
* Constructs a vector with the specified data
* @param elements A 2D array made from a linked list and string array, each string array is 1 element long
*/
public Vector(LinkedList<String[]> rows) {
this.vector = new double[rows.size()];
for (int row = 0; row < rows.size(); row++) {
set(row, Double.parseDouble(rows.get(row)[0]));
}
}
/**
* Constructs a vector with the specified
* number of rows.
* Default value for vector values is zero.
* @param rows The number of rows
*/
public Vector(int rows) {
this.vector = new double[rows];
for (int i = 0; i < rows; i++) {
vector[i] = 0;
}
}
/**
* Constructs a vector with the double array's data
* @param vector The vector
*/
public Vector(double[] vector) {
this.vector = vector;
}
/**
* Retrieves an element in the vector
* @param row The row of the element
* @return The element in the specified row
* @throws IndexOutOfBoundsException if row
* is not valid in the vector
*/
public double get(int row) {
if (row < 0 || row >= rows()) {
throw new IndexOutOfBoundsException();
}
return vector[row];
}
/**
* Sets an element in the vector
* @param row The row of the element
* @param value The value to be set
* @throws IndexOutOfBoundsException if row
* is not valid in the vector
*/
public void set(int row, double value) {
if (row < 0 || row >= rows()) {
throw new IndexOutOfBoundsException();
}
vector[row] = value;
}
/**
* The number of rows in the vector
* @return The number of rows
*/
public int rows() {
return vector.length;
}
/**
* The number of elements in the vector
* @return The number of elements
*/
public int numElements() {
return rows();
}
/**
* Returns the transpose of the given vector.
* @return The transpose of the original vector
*/
public Matrix transpose() {
Matrix transpose = new Matrix(1, numElements());
for (int column = 0; column < rows(); column++) {
transpose.set(0, column, get(column));
}
return transpose;
}
/**
* Returns the norm of the vector as defined in the PDF
* This norm is the largest value in the vector.
* @return The largest value in the vector
*/
public double norm() {
double largest = get(0);
for (int i = 0; i < vector.length; i++) {
if (vector[i] - largest > 0) {
largest = vector[i];
}
}
return largest;
}
/**
* Returns the frobenius norm of the vector
* This norm is the square root of sum of squares of the elements in the vector.
* @return The norm of the matrix
*/
public double normF() {
double sum = 0;
for (int i = 0; i < rows(); i++) {
sum += Math.pow(get(i), 2);
}
return Math.sqrt(sum);
}
/**
* THE FOLLOWING CODE IS USED FOR REPRESENTING THE VECTOR IN STANDARD OUTPUT
* RULES HAVE BEEN IMPLEMENTED AS FOLLOWS:
*
* 1) THE VECTOR WILL BE REPRESENTED AS ITS TRANSPOSE
* 2) EACH ELEMENT IN THE ROW HAS THE SAME WIDTH
* 3) THE LARGEST WIDTH OF ANY INDIVIDUAL ELEMENT IS USED AS THE WIDTH FOR EACH ELEMENT
* 4) A) IF THE NUMBER OF DECIMAL PLACES EXCEEDS 6, THE WIDTH IS FIXED TO A CERTAIN NUMBER "NUMSPACE"
* B) NUMSPACES IS DEFINED AS:
* 1) THE NUMBER OF DIGITS IN THE WHOLE NUMBER PORTION OF THE BIGDECIMAL +
* 2) THE DECIMAL POINT (1 SPACE) +
* 3) THE NUMBER OF DIGITS AFTER THE DECIMAL POINT. EXCLUDING INTIAL ZEROS, IF THIS NUMBER EXCEEDS 6,
* WE SET THE RIGHT SIDE PORTION TO BE #LEADING ZEROS + UP TO 6 DIGITS
* IN THIS WAY, WE ALWAYS END UP WITH AT MOST 6 SIGNIFICANT FIGURES AFTER THE DECIMAL POINT
* 4) SCIENTIFIC NOTATION SUFFIX IS ADDED TO END AND COUNTED TOWARDS NUMSPACES
*/
private static int getNumberOfDecimalPlaces(double number) {
String string = "" + number;
int index = string.indexOf(".");
// If no ".", no digits to right of decimal
if (index < 0) {
return 0;
}
// If only 6 digits or less after decimal place,
// then that's fine
int numAfterDecimal = string.length() - index - 1;
if (numAfterDecimal <= 6) {
return numAfterDecimal;
}
// If more than 6 digits after decimal place,
// find number of relevant digits
// i.e. number of zeros then 6 digits
// Start at the decimal point
// Increment numRelevant and index until we stop getting zeros
index += 1; // Start after the decimal point
int numRelevant = 0;
while (index < string.length() && string.charAt(index) == '0') {
index++;
numRelevant++;
}
// If index >= string.length(), that means there were only zeros after the decimal point
// Shouldn't be possible, but if it is, then no significant figures after decimal point.
if (index >= string.length()) {
return 0;
}
// Otherwise, we hit a nonzero number.
// Index is pointing to that number
numRelevant++;
// Can we hit 5 more numbers?
// For each one we can hit, increment numRelevant.
for (int i = 1; i < 6; i++) {
if (index + i < string.length()) {
numRelevant++;
}
}
return numRelevant;
}
private static int getNumberOfWholeNumbers(double number) {
String string = "" + number;
int count = 0;
for (int i = 0; i < string.length(); i++) {
char x = string.charAt(i);
if (x == '.') {
return count;
} else {
count++;
}
}
return count;
}
private static String getRelevantPortion(double y, int numSpaces) {
String string = "" + y;
String relevantPortion = "";
int index = 0;
String remainder = "";
if (string.indexOf('E') != -1) {
// String is in scientific notation
remainder = string.substring(string.indexOf('E'));
string = string.substring(0, string.indexOf(remainder));
numSpaces -= remainder.length();
}
while (index < numSpaces) {
if (index >= string.length()) {
index = numSpaces;
} else {
relevantPortion += string.substring(index, index + 1);
index++;
}
}
// Rounding the last digit
if (index < string.length()) {
int lastDigit = Integer.parseInt(relevantPortion.substring(relevantPortion.length() - 1));
int digitAfterLast = Integer.parseInt(string.substring(index, index + 1));
if (digitAfterLast >= 5) {
lastDigit++;
}
relevantPortion = relevantPortion.substring(0, relevantPortion.length() - 1) + "" + lastDigit;
}
return relevantPortion + remainder;
}
public String toString() {
int largestRelevantRightDecimal = getNumberOfDecimalPlaces(vector[0]);
int largestNumWholeNumbers = getNumberOfWholeNumbers(vector[0]);
for (double y : vector) {
if (largestNumWholeNumbers < getNumberOfWholeNumbers(y)) {
largestNumWholeNumbers = getNumberOfWholeNumbers(y);
}
if (largestRelevantRightDecimal < getNumberOfDecimalPlaces(y)) {
largestRelevantRightDecimal = getNumberOfDecimalPlaces(y);
}
}
int totalSpace = largestNumWholeNumbers + 1 + largestRelevantRightDecimal;
String formatString = "%" + totalSpace + "s";
String returnString = "[";
for (double x : vector) {
String relevantPortion = getRelevantPortion(x, totalSpace);
returnString += String.format(formatString, relevantPortion) + ", ";
}
returnString = returnString.substring(0, returnString.length() - 2);
returnString += "]^t";
return returnString;
}
}