I am trying to round an array of numbers to three decimal places in java, the reason being that I am running into an OutOfMemoryError (array is exceeding the VM's limit). I was curious if there was a way to do this without writing an entire new method or anything drastic like that.
EDIT: here is all the code
public class GuitarHero {
public static void main(String[] args) {
int index = 0;
double sample = 0.0;
String keyboard ="1234567890qwertyuiopasdfghjklzxcvbnm,";
GuitarString[] string = new GuitarString[keyboard.length()];
for(int i = 0; i < 37; i++) {
double concert = 110.0 * Math.pow(2,i-24);
string[i] = new GuitarString(concert);
}
while (true){
if (StdDraw.hasNextKeyTyped()) {
char key = StdDraw.nextKeyTyped();
index = keyboard.indexOf(key);
if (index >= 0 && index < 37){
string[index].pluck();
}
//sample = string[index].sample() + string[index+1].sample();
//StdAudio.play(sample);
}
for(int i=0; i<37; i++){
sample = string[i].sample();
StdAudio.play(sample);
}
for(int i = 0; i < 37; i++){
string[i].tic();
}
}
}
}
end of code 1
public class GuitarString {
private RingBuffer buffer; // ring buffer
// YOUR OTHER INSTANCE VARIABLES HERE
private int ticTimes = 0;
// create a guitar string of the given frequency
public GuitarString(double frequency) {
// YOUR CODE HERE
int N;
N = (int)(44100/frequency);
buffer = new RingBuffer(N);
for (int i=1; i <=N; i++ ){
buffer.enqueue(0.0);
}
}
// create a guitar string whose size and initial values are given by the array
public GuitarString(double[] init) {
// YOUR CODE HERE
buffer = new RingBuffer(init.length);
for (int i = 0; i < init.length; i++){
buffer.enqueue(init[i]);
}
}
// pluck the guitar string by setting the buffer to white noise
public void pluck() {
// YOUR CODE HERE
while(!buffer.isEmpty()) buffer.dequeue();
while(!buffer.isFull()){
buffer.enqueue(Math.random()-0.5);
}
}
// advance the simulation one time step
public void tic() {
// YOUR CODE HERE
double value1, value2;
value1 = buffer.dequeue();
value2 = buffer.peek();
buffer.enqueue(((value1+value2)/2)*0.996);
ticTimes++;
}
// return the current sample
public double sample() {
// YOUR CODE HERE
return buffer.peek();
}
// return number of times tic was called
public int time() {
// YOUR CODE HERE
return ticTimes;
}
public static void main(String[] args) {
int N = Integer.parseInt(args[0]);
double[] samples = { .2, .4, .5, .3, -.2, .4, .3, .0, -.1, -.3 };
GuitarString testString = new GuitarString(samples);
for (int i = 0; i < N; i++) {
int t = testString.time();
double sample = testString.sample();
System.out.printf("%6d %8.4f\n", t, sample);
testString.tic();
}
}
}
end of code 2
public class RingBuffer {
private int first; // index of first item in buffer
private int last; // index of last item in buffer
private int size; // current number of items of buffer
private double[] buffer;
// create an empty buffer, with given max capacity
public RingBuffer(int capacity) {
// YOUR CODE HERE
buffer = new double[capacity];
first =0;
last =capacity-1;
size =0;
}
// return number of items currently in the buffer
public int size() {
// YOUR CODE HERE
return size;
}
// is the buffer empty (size equals zero)?
public boolean isEmpty() {
// YOUR CODE HERE
if (size == 0)
return true;
else
return false;
}
// is the buffer full (size equals array capacity)?
public boolean isFull() {
// YOUR CODE HERE
if (size == buffer.length)
return true;
else
return false;
}
// add item x to the end
public void enqueue(double x) {
if (isFull()) { throw new RuntimeException("Ring buffer overflow"); }
// YOUR CODE HERE
last = (last+1)%buffer.length;
buffer[last]=x;
size++;
}
// delete and return item from the front
public double dequeue() {
if (isEmpty()) { throw new RuntimeException("Ring buffer underflow"); }
// YOUR CODE HERE
double temp = buffer[first];
first = (first+1)% buffer.length;
size--;
return temp;
}
// return (but do not delete) item from the front
public double peek() {
if (isEmpty()) { throw new RuntimeException("Ring buffer underflow"); }
// YOUR CODE HERE
return buffer[first];
}
// a simple test of the constructor and methods in RingBuffer
public static void main(String[] args) {
int N = Integer.parseInt(args[0]);
RingBuffer buffer = new RingBuffer(N);
for (int i = 1; i <= N; i++) {
buffer.enqueue(i);
}
double t = buffer.dequeue();
buffer.enqueue(t);
System.out.println("Size after wrap-around is " + buffer.size);
while (buffer.size() >= 2) {
double x = buffer.dequeue();
double y = buffer.dequeue();
buffer.enqueue(x + y);
}
System.out.println(buffer.peek());
}
}
Thanks!
Well in the first iteration of that loop the code is trying to allocate an array of 1,681,534,603 doubles (44100 / (110 * 2^-22)), which would require about 3GB of memory. I suggest you find a different solution.
Related
I am creating an Array List differentServices composed of objects Services I am creating.
When I'm trying to get data from a file which would serve as services with parameters service name, service file name, and service fee and while printing the values of my array list differentService I note that the name of the services in my arraylist are all different and according to the file, the service fees of the different objects in the arraylist are all different and according to the file too, but the filename of every object in differentServices is the same even though the way I declare the new Services() is the same as for service name and service fee.
I'm trying to understand why as I need the data of every service to be different.
import java.util.*;
import java.io.*;
public class Assignment2_main {
Services[] a; //a is a Template object
int size;
static String name;
static String fileName;
static double usageFee;
static String toRemoveString = "service=";
public void ArrayList() {
a = (Services[]) new Object[10]; //a defined as a list of 10 Objects T
size = 0;
}
public void add(Services item) { //Add item to the end
if(size == a.length) { //If the size is equal to the length of a
doubleArray(); //Double the array
}
a[size++] = item; //The last object of the array takes the value of item
}
public void add(int pos, Services item) { //Add item to specific position
if(size == a.length) {//Double the array if the size is equal to the length of a
doubleArray();
}
for(int i=size-1; i>pos; i--) { //Every element after the position specified is changing index by one
a[i+1] = a[i];
}
a[pos] = item; //The element at position pos takes the value of item
size++; //Increment the size
}
public Services get(int pos) { //Get value at position pos
if(pos >= size || pos < 0) { //If the specified position is out of bound, display error
throw new IndexOutOfBoundsException();
}
return a[pos]; //Return the object at position pos
}
public Services remove(int pos) { //Remove element at position pos
if(pos >= size || pos < 0) { //If the specified position is out of bound, display error
throw new IndexOutOfBoundsException();
}
Services temp = a[pos]; //temp object T takes value of the element to remove
for(int i=pos; i<size-1; i++) { //Every element after the position specified is changing index by one
a[i] = a[i+1];
}
size--; //size of the array decrements by one
return temp; //Return the removed value
}
public int size() { //Return the size of the list
return size;
}
void doubleArray() {
Services[] newArray = (Services[])new Object[a.length*2]; //Doubles the length of the array a
for(int i = 0; i < size; i++) { //places all the elements of the array a into array newArray
newArray[i] = a[i];
}
a = newArray; //places all the elements back into a
}
public static void main(String[] args) {
ArrayList<Services> differentServices = new ArrayList<Services>();
try {
File configFile = new File("/Users/Yohan/Desktop/CS245Assignment2/config.txt");
Scanner scanConfigFile = new Scanner(configFile);
while (scanConfigFile.hasNextLine()) {
String data = scanConfigFile.nextLine();
String[] token = data.split(",");
for(int i=0;i<token.length;i++) {
if(i==0) {
name = token[i].replaceAll("service=", "");
}
else if(i==1) {
fileName = token[i];
}
else if(i==2) {
usageFee = Double.parseDouble(token[i]);
}
else {
System.out.println("Logical Error");
}
}
Services newService = new Services(name, fileName, usageFee);
//Problem before this
differentServices.add(newService);
System.out.println(differentServices.get(0).fileName);
}
scanConfigFile.close();
} catch (FileNotFoundException e) {
System.out.println("An error occurred.");
e.printStackTrace();
}
System.out.println(differentServices.get(0).fileName);
String userItemInput = "", userSizeInput = "", userQuantityInput = "";
Scanner input = new Scanner(System.in);
while(!(userItemInput.contentEquals("done"))) {
System.out.println("Enter your next item or 'done':");
userItemInput = input.nextLine();
if (userItemInput.contentEquals("done")) {
continue;
}
System.out.println("Size:");
userSizeInput = input.nextLine();
System.out.println("Quantity:");
userQuantityInput = input.nextLine();
}
}
}
Here is the configuration file:
service=Instacart,instacart.csv,5.99
service=Prime,amazon.csv,4.00
service=Safeway,safeway.csv,3.99
service=GoogleDelivery,google.csv,6.99
service=Basket,basket.csv,2.50
And here is my Service.java file:
public class Services {
public String name = "";
public static String fileName = "";
public double usageFee = 0;
//constructor
public Services(String name, String fileName, double usageFee) {
this.name = name;
this.fileName = fileName;
this.usageFee = usageFee;
}
}
I know similar questions have been asked before but I have found the answers confusing. I am trying to make a program that will find every combination of an array-list with no repetitions and only of the maximum size. If the list has 4 items it should print out only the combinations with all 4 items present. This is what I have so far:
public main(){
UI.initialise();
UI.addButton("Test", this::testCreate);
UI.addButton("Quit", UI::quit);
}
public void createCombinations(ArrayList<String> list, String s, int depth) {
if (depth == 0) {
return;
}
depth --;
for (int i = 0; i < list.size(); i++) {
if (this.constrain(s + "_" + list.get(i), list.size())) {
UI.println(s + "_" + list.get(i));
}
createCombinations(list, s + "_" + list.get(i), depth);
}
}
public void testCreate() {
ArrayList<String> n = new ArrayList<String>();
n.add("A"); n.add("B"); n.add("C"); n.add("D");
this.createCombinations(n , "", n.size());
}
public boolean constrain(String s, int size) {
// Constrain to only the maximum length
if ((s.length() != size*2)) {
return false;
}
// Constrain to only combinations without repeats
Scanner scan = new Scanner(s).useDelimiter("_");
ArrayList<String> usedTokens = new ArrayList<String>();
String token;
while (scan.hasNext()) {
token = scan.next();
if (usedTokens.contains(token)) {
return false;
} else {
usedTokens.add(token);
}
}
// If we fully iterate over the loop then there are no repitions
return true;
}
public static void main(String[] args){
main obj = new main();
}
This prints out the following which is correct:
_A_B_C_D
_A_B_D_C
_A_C_B_D
_A_C_D_B
_A_D_B_C
_A_D_C_B
_B_A_C_D
_B_A_D_C
_B_C_A_D
_B_C_D_A
_B_D_A_C
_B_D_C_A
_C_A_B_D
_C_A_D_B
_C_B_A_D
_C_B_D_A
_C_D_A_B
_C_D_B_A
_D_A_B_C
_D_A_C_B
_D_B_A_C
_D_B_C_A
_D_C_A_B
_D_C_B_A
This works for small lists but is very inefficient for larger ones. I am aware that what I have done is completely wrong but I want to learn the correct way. Any help is really appreciated. Thanks in advance.
P.S. This is not homework, just for interest although I am a new CS student (if it wasn't obvious).
Implementing Heap's algorithm in Java:
import java.util.Arrays;
public class Main {
public static void swap(final Object[] array, final int index1, final int index2) {
final Object tmp = array[index1];
array[index1] = array[index2];
array[index2] = tmp;
}
public static void printPermutations_HeapsAlgorithm(final int n, final Object[] array) {
final int[] c = new int[n];
for (int i = 0; i < c.length; ++i)
c[i] = 0;
System.out.println(Arrays.toString(array)); //Consume first permutation.
int i=0;
while (i < n) {
if (c[i] < i) {
if ((i & 1) == 0)
swap(array, 0, i);
else
swap(array, c[i], i);
System.out.println(Arrays.toString(array)); //Consume permutation.
++c[i];
i=0;
}
else
c[i++] = 0;
}
}
public static void main(final String[] args) {
printPermutations_HeapsAlgorithm(4, new Character[]{'A', 'B', 'C', 'D'});
}
}
Possible duplicate of this.
I have applied the KNN algorithm for classifying handwritten digits. the digits are in vector format initially 8*8, and stretched to form a vector 1*64..
As it stands my code applies the kNN algorithm but only using k = 1. I'm not entirely sure how to alter the value k after attempting a couple of things I kept getting thrown errors. If anyone could help push me in the right direction it would be really appreciated. The training dataset can be found here and the validation set here.
ImageMatrix.java
import java.util.*;
public class ImageMatrix {
private int[] data;
private int classCode;
private int curData;
public ImageMatrix(int[] data, int classCode) {
assert data.length == 64; //maximum array length of 64
this.data = data;
this.classCode = classCode;
}
public String toString() {
return "Class Code: " + classCode + " Data :" + Arrays.toString(data) + "\n"; //outputs readable
}
public int[] getData() {
return data;
}
public int getClassCode() {
return classCode;
}
public int getCurData() {
return curData;
}
}
ImageMatrixDB.java
import java.util.*;
import java.io.*;
import java.util.ArrayList;
public class ImageMatrixDB implements Iterable<ImageMatrix> {
private List<ImageMatrix> list = new ArrayList<ImageMatrix>();
public ImageMatrixDB load(String f) throws IOException {
try (
FileReader fr = new FileReader(f);
BufferedReader br = new BufferedReader(fr)) {
String line = null;
while((line = br.readLine()) != null) {
int lastComma = line.lastIndexOf(',');
int classCode = Integer.parseInt(line.substring(1 + lastComma));
int[] data = Arrays.stream(line.substring(0, lastComma).split(","))
.mapToInt(Integer::parseInt)
.toArray();
ImageMatrix matrix = new ImageMatrix(data, classCode); // Classcode->100% when 0 -> 0% when 1 - 9..
list.add(matrix);
}
}
return this;
}
public void printResults(){ //output results
for(ImageMatrix matrix: list){
System.out.println(matrix);
}
}
public Iterator<ImageMatrix> iterator() {
return this.list.iterator();
}
/// kNN implementation ///
public static int distance(int[] a, int[] b) {
int sum = 0;
for(int i = 0; i < a.length; i++) {
sum += (a[i] - b[i]) * (a[i] - b[i]);
}
return (int)Math.sqrt(sum);
}
public static int classify(ImageMatrixDB trainingSet, int[] curData) {
int label = 0, bestDistance = Integer.MAX_VALUE;
for(ImageMatrix matrix: trainingSet) {
int dist = distance(matrix.getData(), curData);
if(dist < bestDistance) {
bestDistance = dist;
label = matrix.getClassCode();
}
}
return label;
}
public int size() {
return list.size(); //returns size of the list
}
public static void main(String[] argv) throws IOException {
ImageMatrixDB trainingSet = new ImageMatrixDB();
ImageMatrixDB validationSet = new ImageMatrixDB();
trainingSet.load("cw2DataSet1.csv");
validationSet.load("cw2DataSet2.csv");
int numCorrect = 0;
for(ImageMatrix matrix:validationSet) {
if(classify(trainingSet, matrix.getData()) == matrix.getClassCode()) numCorrect++;
} //285 correct
System.out.println("Accuracy: " + (double)numCorrect / validationSet.size() * 100 + "%");
System.out.println();
}
In the for loop of classify you are trying to find the training example that is closest to a test point. You need to switch that with a code that finds K of the training points that is the closest to the test data. Then you should call getClassCode for each of those K points and find the majority(i.e. the most frequent) of the class codes among them. classify will then return the major class code you found.
You may break the ties (i.e. having 2+ most frequent class codes assigned to equal number of training data) in any way that suits your need.
I am really inexperienced in Java, but just by looking around the language reference, I came up with the implementation below.
public static int classify(ImageMatrixDB trainingSet, int[] curData, int k) {
int label = 0, bestDistance = Integer.MAX_VALUE;
int[][] distances = new int[trainingSet.size()][2];
int i=0;
// Place distances in an array to be sorted
for(ImageMatrix matrix: trainingSet) {
distances[i][0] = distance(matrix.getData(), curData);
distances[i][1] = matrix.getClassCode();
i++;
}
Arrays.sort(distances, (int[] lhs, int[] rhs) -> lhs[0]-rhs[0]);
// Find frequencies of each class code
i = 0;
Map<Integer,Integer> majorityMap;
majorityMap = new HashMap<Integer,Integer>();
while(i < k) {
if( majorityMap.containsKey( distances[i][1] ) ) {
int currentValue = majorityMap.get(distances[i][1]);
majorityMap.put(distances[i][1], currentValue + 1);
}
else {
majorityMap.put(distances[i][1], 1);
}
++i;
}
// Find the class code with the highest frequency
int maxVal = -1;
for (Entry<Integer, Integer> entry: majorityMap.entrySet()) {
int entryVal = entry.getValue();
if(entryVal > maxVal) {
maxVal = entryVal;
label = entry.getKey();
}
}
return label;
}
All you need to do is adding K as a parameter. Keep in mind, however, that the code above does not handle ties in a particular way.
I'm making a program that reads some data from a text file and then takes that data and finds the minimum, maximum, and average of the numbers. For some reason I'm getting a lot of ridiculous errors I've never seen before. Here is my code:
import java.io.File;
import java.util.Scanner;
import java.io.FileWriter;
public class Lab1 {
static int count = 0;
static int[] newData2 = new int[count];
// Method for reading the data and putting it into different arrays
static int[] readData() {
File f = new File("data.txt");
int[] newData = new int[100];
try {
Scanner s = new Scanner(f);
while (s.hasNext()) {
newData[count++] = s.nextInt();
}
for (int i = 0; i < newData2.length; i++) {
newData[i] = newData2[i];
return newData2;
}
} catch (Exception e) {
System.out.println("Could not read the file.");
}
}
static int min(int[] newData2) {
int min = newData2[0];
for (int i = 0; i < newData2.length; i++) {
if (newData2[i] < min) {
min = newData2[i];
}
}
return min;
}
static int max(int[] newData2) {
int max = newData2[0];
for (int i = 0; i < newData2.length; i++) {
if (newData2[i] > max) {
max = newData2[i];
}
}
return max;
}
static double average(int[] newData2) {
double average = 0;
int sum = 0;
for (int i = 0; i < newData2.length; i++) {
sum = newData2[i];
}
average = sum / newData2.length;
return average;
}
/*
* static int stddev(int[] newData2) { int[] avgDif = new
* int[newData2.length]; for(int i = 0; i < newData2.length; i++) {
* avgDif[i] = (int) (average(newData2) - newData2[i]); }
*
* }
*/
void write(String newdata, int min, int max, double average, int stddev) {
try {
File file = new File("stats.txt");
file.createNewFile();
FileWriter writer = new FileWriter("stats.txt");
writer.write("Minimum: " + min + "Maximum: " + max + "Average: " + average);
writer.close();
}catch(Exception e) {
System.out.println("Unable to write to the file.");
}
public static void main(String[] args) {
}
}
}
I have an error in my readData method, and it tells me that:
This method must return a result type of int[].
I'm literally returning an int array so I don't understand what the problem here is.
Then in my main method it says void is an invalid type for the variable main.
Here are some pointers:
each exit point of a method returning something must return something, if the line new Scanner(f); throws an exception, the first return is not reached, so you need a default one, like this:
private int[] readData() {
File f = new File("data.txt");
int count = 0;
int[] newData = new int[100];
try {
Scanner s = new Scanner(f);
while (s.hasNext()) {
newData[count++] = s.nextInt(); // maybe you should handle the case where your input is too large for the array "newData"
}
return Arrays.copyOf(newData, count);
} catch (Exception e) {
System.out.println("Could not read the file.");
}
return null;
}
To reduce the size of an array, you should use Arrays.copyOf (see below)
You should avoid static fields (and in your case none are required)
Your method min and max are assuming there are elements in the array (at least one), you should not do that (or test it with an if):
private int min(int[] data) {
int min = Integer.MAX_VALUE; // handy constant :)
for (int i = 0; i < data.length; i++) {
if (data[i] < min) {
min = data[i];
}
}
return min;
}
private int max(int[] data) {
int max = 0;
for (int i = 0; i < data.length; i++) {
if (data[i] > max) {
max = data[i];
}
}
return max;
}
In your average method there are a few mistakes:
private double average(int[] data) {
int sum = 0;
for (int i = 0; i < data.length; i++) {
sum += data[i]; // here if you want a sum it's += not =
}
return (1.0 * sum) / data.length; // you want a double division, local "average" was useless
}
arrays are iterables so you can use "new style" for loops:
for (int value : newData) {
// use value
}
Some reading:
Java Integer division: How do you produce a double?
“Missing return statement” within if / for / while
static int[] readData() {
File f = new File("data.txt");
int[] newData = new int[100];
try {
Scanner s = new Scanner(f);
while (s.hasNext()) {
newData[count++] = s.nextInt();
}
for (int i = 0; i < newData2.length; i++) {
newData[i] = newData2[i];
return newData2;
}
} catch (Exception e) {
System.out.println("Could not read the file.");
}
//TODO: return something here if there is some kind of error
}
Because of the try-catch block you need to account for every possibility that could occur. When you return the array when the program succeeds you are expecting a return, but when there is an exception the program still expects a return value, but you did not provide one.
I'm working on a project for a class, and I think I've got it mostly figured out, but it keeps giving me different Exception errors and now I'm stumped.
The instructions can be found here: http://www.cse.ohio-state.edu/cse1223/currentsem/projects/CSE1223Project11.html
Here is the code I have thus far, currently giving me and IndexOutOfBounds exception in the getMaximum method.
Any help would be much appreciated.
import java.io.*;
import java.util.*;
public class Project11a {
public static void main(String[] args) throws FileNotFoundException {
Scanner keyboard = new Scanner(System.in);
System.out.print("Enter an input file name: ");
String fileName = keyboard.nextLine();
Scanner in = new Scanner(new File(fileName));
System.out.print("Enter an output file name: ");
String outFile = keyboard.nextLine();
PrintWriter outputFile = new PrintWriter(outFile);
while (in.hasNextLine()) {
String name = in.nextLine();
List<Integer> series = readNextSeries(in);
int mean = getAverage(series);
int median = getMedian(series);
int max = getMaximum(series);
int min = getMinimum(series);
outputFile.printf("%-22s%6d%n", name, mean, median, max, min);
}
in.close();
outputFile.close();
}
// Given a Scanner as input read in a list of integers one at a time until a
// negative
// value is read from the Scanner. Store these integers in an
// ArrayList<Integer> and
// return the ArrayList<Integer> to the calling program.
private static List<Integer> readNextSeries(Scanner inScanner) {
List<Integer> nextSeries = new ArrayList<Integer>();
while (inScanner.hasNextInt()) {
int currentLine = inScanner.nextInt();
if (currentLine != -1) {
nextSeries.add(currentLine);
} else {
break;
}
}
return nextSeries;
}
// Given a List<Integer> of integers, compute the median of the list and
// return it to
// the calling program.
private static int getMedian(List<Integer> inList) {
Collections.sort(inList);
int middle = inList.size() / 2;
int median = -1;
if (inList.size() % 2 == 1) {
median = inList.get(middle);
} else {
try {
median = (inList.get(middle - 1) + inList.get(middle)) / 2;
} catch (Exception e) {
}
}
return median;
}
// Given a List<Integer> of integers, compute the average of the list and
// return it to
// the calling program.
private static int getAverage(List<Integer> inList) {
int average = 0;
if (inList.size() == 0) {
return 0;
}
for (int i = 0; i < inList.size(); i++) {
average += inList.get(i);
}
return (average / inList.size());
}
// Given a List<Integer> of integers, compute the maximum of the list and
// return it to
// the calling program.
private static int getMaximum(List<Integer> inList) {
int max = inList.get(0);
for (int i = 1; i < inList.size(); i++) {
if (inList.get(i) > max) {
max = inList.get(i);
}
}
return max;
}
// Given a List<Integer> of integers, compute the maximum of the list and
// return it to
// the calling program.
private static int getMinimum(List<Integer> inList) {
int min = inList.get(0);
for (int i = 1; i < inList.size(); i++) {
if (inList.get(i) < min) {
min = inList.get(i);
}
}
return min;
}
}
Seemed like that your list is empty.
What can triggered the exception is the statement:
int max = inList.get(0);
So your inList do not have the value in the first index,which means the inList is empty.