I'm quite new in Java and I'm getting this error I can manage to understand where it is coming from. Im doing FFT analysis and I'm getting an error:
java.lang.ArrayIndexOutOfBoundsException: 66,
at DrawingFunction.main(DrawingFunction.java:66)
at AnimationGen.begin(AnimationGen.java:54)
at FFTclass.main2(FFTclass.java:213)
at fftTry.main(fftTry.java:34)
the codes are this for the fftTry:
public static void main(String[] args) {
final String NEWLINE = "\n";
String inputFile = "C:/Users/USER/Downloads/DD.wav"; // Place the wav file in the top level directory, ie S:/input.wav
File fileLocation = new File(inputFile);
System.out.println("START");
try {
double[] complexNumber = readFully(fileLocation);
System.out.println(NEWLINE + "Read file");
double[] realPart = complexNumber;
double[] imagPart = new double[realPart.length];
System.out.println("Length = " + realPart.length);
FFTclass FFT = new FFTclass(1024);
FFT.main2(realPart,imagPart,1024);
//for (int i = 0; i < complexNumber.length; ++i) {
// System.out.println(complexNumber[i]);
//}
} catch (Exception ex) {
ex.printStackTrace();
}
}
static double[] readFully(File file) throws UnsupportedAudioFileException, IOException {
AudioInputStream in = AudioSystem.getAudioInputStream(file);
AudioFormat fmt = in.getFormat();
double sampleRate = fmt.getSampleRate();
double frameSize = fmt.getFrameSize();
double auidioDuration = fmt.getFrameRate();
double channels = fmt.getChannels();
System.out.println("File length = " + file.length() + " ");
System.out.println("Sample Rate = " + sampleRate + " per second");
System.out.println("Frame size = " + frameSize + " per second");
System.out.println("Frame rate = " + auidioDuration + " per second");
System.out.println("Channels = " + channels);
System.out.println("Length in time = " + (file.length()/frameSize * auidioDuration) + " seconds");
System.out.println("Length in time in minutes = " + (int)(file.length()/(frameSize* auidioDuration *60)) + " minutes and " + ( (file.length()/(frameSize* auidioDuration *60))- (int)(file.length()/(frameSize* auidioDuration *60)) )* 60 + " seconds");
byte[] bytes;
try {
if (fmt.getEncoding() != Encoding.PCM_SIGNED) {
throw new UnsupportedAudioFileException();
}
// read the data fully
bytes = new byte[in.available()];
in.read(bytes);
} finally {
in.close();
}
int bits = fmt.getSampleSizeInBits();
double max = Math.pow(2, bits - 1);
ByteBuffer bb = ByteBuffer.wrap(bytes);
bb.order(fmt.isBigEndian() ?
ByteOrder.BIG_ENDIAN : ByteOrder.LITTLE_ENDIAN);
double[] samples = new double[bytes.length * 8 / bits];
// convert sample-by-sample to a scale of
// -1.0 <= samples[i] < 1.0
for (int i = 0; i < samples.length; ++i) {
switch (bits) {
case 8:
samples[i] = (bb.get() / max);
break;
case 16:
samples[i] = (bb.getShort() / max);
break;
case 32:
samples[i] = (bb.getInt() / max);
break;
case 64:
samples[i] = (bb.getLong() / max);
break;
default:
throw new UnsupportedAudioFileException();
}
}
return samples;
}
For the FFTclass:
int n, m;
// Lookup tables. Only need to recompute when size of FFT changes.
double[] cos;
double[] sin;
double[] window;
public FFTclass(int n) {
this.n = n;
this.m = (int)(Math.log(n) / Math.log(2));
// Make sure n is a power of 2
if(n != (1<<m))
throw new RuntimeException("FFT length must be power of 2");
// precompute tables
cos = new double[n/2];
sin = new double[n/2];
// for(int i=0; i<n/4; i++) {
// cos[i] = Math.cos(-2*Math.PI*i/n);
// sin[n/4-i] = cos[i];
// cos[n/2-i] = -cos[i];
// sin[n/4+i] = cos[i];
// cos[n/2+i] = -cos[i];
// sin[n*3/4-i] = -cos[i];
// cos[n-i] = cos[i];
// sin[n*3/4+i] = -cos[i];
// }
for(int i=0; i<n/2; i++) {
cos[i] = Math.cos(-2*Math.PI*i/n);
sin[i] = Math.sin(-2*Math.PI*i/n);
}
makeWindow();
}
protected void makeWindow() {
// Make a blackman window:
// w(n)=0.42-0.5cos{(2*PI*n)/(N-1)}+0.08cos{(4*PI*n)/(N-1)};
window = new double[n];
for(int i = 0; i < window.length; i++)
window[i] = 0.42 - 0.5 * Math.cos(2*Math.PI*i/(n-1))
+ 0.08 * Math.cos(4*Math.PI*i/(n-1));
}
public double[] getWindow() {
return window;
}
/***************************************************************
00089 * fft.c
00090 * Douglas L. Jones
00091 * University of Illinois at Urbana-Champaign
00092 * January 19, 1992
00093 * http://cnx.rice.edu/content/m12016/latest/
00094 *
00095 * fft: in-place radix-2 DIT DFT of a complex input
00096 *
00097 * input:
00098 * n: length of FFT: must be a power of two
00099 * m: n = 2**m
00100 * input/output
00101 * x: double array of length n with real part of data
00102 * y: double array of length n with imag part of data
00103 *
00104 * Permission to copy and use this program is granted
00105 * as long as this header is included.
00106 ****************************************************************/
public void fft(double[] x, double[] y)
{
int i,j,k,n1,n2,a;
double c,s,e,t1,t2;
// Bit-reverse
j = 0;
n2 = n/2;
for (i=1; i < n - 1; i++) {
n1 = n2;
while ( j >= n1 ) {
j = j - n1;
n1 = n1/2;
}
j = j + n1;
if (i < j) {
t1 = x[i];
x[i] = x[j];
x[j] = t1;
t1 = y[i];
y[i] = y[j];
y[j] = t1;
}
}
// FFT
n1 = 0;
n2 = 1;
for (i=0; i < m; i++) {
n1 = n2;
n2 = n2 + n2;
a = 0;
for (j=0; j < n1; j++) {
c = cos[a];
s = sin[a];
a += 1 << (m-i-1);
for (k=j; k < n; k=k+n2) {
t1 = c*x[k+n1] - s*y[k+n1];
t2 = s*x[k+n1] + c*y[k+n1];
x[k+n1] = x[k] - t1;
y[k+n1] = y[k] - t2;
x[k] = x[k] + t1;
y[k] = y[k] + t2;
}
}
}
}
// Test the FFT to make sure it's working
public static void main2(double[] re, double[] im, int N) {
FFTclass fft = new FFTclass(N);
double[] window = fft.getWindow();
double[] ang;
double[] amplitude;
// Impulse
re[0] = 1; im[0] = 0;
for(int i=1; i<N; i++)
re[i] = im[i] = 0;
System.out.println("Impulse");
beforeAfter(fft, re, im);
// Nyquist
for(int i=0; i<N; i++) {
re[i] = Math.pow(-1, i);
im[i] = 0;
}
System.out.println("Nyquist");
beforeAfter(fft, re, im);
// Single sin
for(int i=0; i<N; i++) {
re[i] = Math.cos(2*Math.PI*i / N);
im[i] = 0;
}
System.out.println("Single sin");
beforeAfter(fft, re, im);
// Ramp
for(int i=0; i<N; i++) {
re[i] = i;
im[i] = 0;
}
System.out.println("Ramp");
beforeAfter(fft, re, im);
amplitude = new double[re.length];
ang = new double[re.length];
for(int i=0; i<re.length;i++)
{
amplitude[i] = Math.sqrt( (re[i]*re[i])+ (im[i]*im[i]) );
//Calculate and return the phase
// angle in degrees.
if(im[i] == 0.0 && re[i] == 0.0){ang[i] = 0.0;}
else{ang[i] = Math.atan(im[i]/re[i])*180.0/Math.PI;}
if(re[i] < 0.0 && im[i] == 0.0){ang[i] = 180.0;}
else if(re[i] < 0.0 && im[i] == -0.0){
ang[i] = -180.0;}
else if(re[i] < 0.0 && im[i] > 0.0){
ang[i] += 180.0;}
else if(re[i] < 0.0 && im[i] < 0.0){
ang[i] += -180.0;}
}
for(int i = 100500; i<100600; i++)
{
System.out.print( '\n' + "Magnitude["+i+"] = " +amplitude[i]+ ", ");
System.out.print( '\n' + "Angle phase["+i+"] = " +ang[i]+ ", ");
}
long time = System.currentTimeMillis();
double iter = 30000;
for(int i=0; i<iter; i++)
fft.fft(re,im);
time = System.currentTimeMillis() - time;
System.out.println("\n" + "Averaged " + (time/iter) + "ms per iteration");
System.out.println("Time: " + (time) + "ms");
AnimationGen animation = new AnimationGen();
animation.begin(amplitude);
}
protected static void beforeAfter(FFTclass fft, double[] re, double[] im) {
System.out.println("Before: ");
printReIm(re, im);
fft.fft(re, im);
System.out.println("After: ");
printReIm(re, im);
}
protected static void printReIm(double[] re, double[] im) {
System.out.print("Re: [");
//for(int i=0; i<re.length; i++)
System.out.println("i = " + re.length);
for(int i=100550; i<100650; i++)
System.out.print(((int)(re[i]*1000)/1000.0) + " ");
System.out.print("]\nIm: [");
//for(int i=0; i<im.length; i++)
for(int i=100550; i<100650; i++)
System.out.print(((int)(im[i]*1000)/1000.0) + " ");
System.out.println("]");
}
The AnimationGen:
public int frameWidth = 1920;
public int frameHeigth = 1080;
public int fps = 30;
public void begin(double[] magnitude)
{
int magnitudeLength = magnitude.length;
int value = (int)magnitudeLength/44100;
double [][][] magnitudesPerSecond = new double[value][fps][(int)44100/fps];
for(int i = 0; i < value;i++) {
for(int j = 0; j < fps;j++) {
for (int k = 0; k < (int)44100/fps; k++) {
int arraynumber = k + (j*fps) +(i * (int)44100/fps);
magnitudesPerSecond[i][j][k] = magnitude[arraynumber];
}
}
}
System.out.println("i = " + magnitudesPerSecond.length);
System.out.println("j = " + magnitudesPerSecond[0].length);
System.out.println("k = " + magnitudesPerSecond[0][0].length);
DrawingFunction DF = new DrawingFunction();
DF.main(value, fps, magnitudesPerSecond);
}
And the final DrawingFunction
public int second = 0;
Timer t = new Timer();
TimerTask timeTask = new TimerTask() {
#Override
public void run() {
second++;
}
};
public double addingAngle = 0;
public int frameWidth = 1920;
public int frameHeigth = 1080;
public int value;
public int fps;
public double[][][] magnitude;
double xPoint[][][];
double yPoint[][][];
public void main(int value, int fps, double[][][] magnitude) {
this.value = value;
this.fps = fps;
this.magnitude = magnitude;
///////////////////////////////////////////////////////////////////////////////////////////////////
double xPoint[][][] = new double[value][fps][64];
double yPoint[][][] = new double[value][fps][64];
for (int counter = 0; counter < value; counter++) {
for (int i = 0; i < fps; i++) {
for (int j = 0; j < (44100 / fps); j += ((44100 / fps) / 64)) {
xPoint[counter][i][j] = magnitude[counter][i][j];
for (int t = 0; t < ((44100 / fps) / 65); t++) { //64 is the number of bands taken into and only 55 from them are used
if(j+t < magnitude[0][0].length) {
xPoint[counter][i][j] += magnitude[counter][i][j + t];
}
System.out.println("Here xPoint[" +i+"]["+j+"]" + (j + t));
}
xPoint[counter][i][j] /= (int) ((44100 / fps) / 64);
}
int t = 0;
for (double angle = addingAngle; angle < 2 * Math.PI + addingAngle; angle += 2 * Math.PI / 55) {
xPoint[counter][i][t] *= Math.cos(angle); //All X points [second][frame][band]
yPoint[counter][i][t] *= Math.sin(angle); //All Y points [second][frame][band]
t++;
}
addingAngle += Math.PI / 110; //110 = 55 points * 2 so rotation is slower
}
this.xPoint = xPoint;
this.yPoint = yPoint;
// Up to here we have 64 xPoints and 64 yPoints, but only the first 55 of each are multiplied by the angle
// jl.setIcon(new ImageIcon("/images/T.png"));
}
for (int i = 0; i < 55; i++) {
System.out.println("Point[" + i + "] is: " + xPoint[0][0][i]);
}
///////////////////////////////////////////////////////////////////////////////////////////////////
JFrame window = new JFrame();
window.add(new DrawingFunction());
window.pack();
window.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
window.setLocationRelativeTo(null);
window.setSize(frameWidth, frameHeigth);
window.setBackground(Color.blue);
window.setVisible(true);
repaint();
}
#Override
protected void paintComponent(Graphics g) {
g.setColor(Color.black);
g.fillRect(800, 500, 300, 300); //g.translate(frameWidth/2, frameHeigth/2);
Polygon p = new Polygon();
for (int i = 0; i < 55; i++)
p.addPoint(15 * (int) xPoint[0][0][i], 15 * (int) yPoint[0][0][i]);
g.setColor(Color.black);
g.drawPolygon(p);
g.fillRect(800, 800, 400, 400);
validate(); // So image appears even if screen is small
I know the code is long, hope its not hard to read, its the first time I make a question here
I would look at these lines here:
double xPoint[][][] = new double[value][fps][64];
//...
for (int j = 0; j < (44100 / fps); j += ((44100 / fps) / 64)) {
xPoint[counter][i][j] = magnitude[counter][i][j];
Note that the inputted fps is 30, so ((44100 / 30) / 64)) = 22.96875 (or 22 as an int). So when this loop iterates, j will be as follows:
j = 0
j = 22
j = 44
j = 66 (Array out of bounds)
The value of fps is 30 (if I'm not missing anything). 44100 / fps = 1,470. So, j goes from 0 to 1,469. But, the third dimension of your array is only 64...
double xPoint[][][] = new double[value][fps][64];
double yPoint[][][] = new double[value][fps][64];
for (int counter = 0; counter < value; counter++) {
for (int i = 0; i < fps; i++) {
for (int j = 0; j < (44100 / fps); j += ((44100 / fps) / 64)) {
xPoint[counter][i][j] = magnitude[counter][i][j];
Related
Okay firstly I'm sorry I know that I'm not intelligent enough. I'm bad at Math.
I couldn't write an algorithm to this question.
System gives us int x, int y, int boundary and wants us to find which numbers up to boundary satisfy the rule as
some_number = x^i + y^j
Boundary <= 10^6
i and j > = 0
x and y < 100
for example x = 2, y = 3 and boundary= 5,
2 = 2^0 + 3^0
3 = 2^1 + 3^0
4 = 2^0 + 3^1
5 = 2^1 + 3^1
output : 2,3,4,5
import java.util.ArrayList;
public class Main {
public static ArrayList<Integer> find_numbers(int x, int y, int boundary) {
ArrayList<Integer> res = new ArrayList<Integer>();
int num = 0;
int remain_x = 0, remain_y = 0;
int count_x = 0, count_y = 0;
if (boundary >= 2) {
res.add(2);
}
for (int i = 3; i <= boundary; ++i) {
if(i == x+y)
res.add(i);
count_x = 0;
count_y = 0;
num = i;
while (num > 0) {
remain_x = num % x;
if (remain_x == 0) {
count_x++;
} else {
while (num > 0) {
remain_y = num % y;
if (remain_y == 0) {
count_y++;
}
num = num / y;
}
}
num = num / x;
}
System.out.println("i =>" +i);
System.out.println("x=>" + count_x);
System.out.println("y =>" + count_y);
}
return res;
}
public static void main(String[] args) {
ArrayList<Integer> res = new ArrayList<Integer>();
int x = 1 + (int) (Math.random() * 100);
int y = 1 + (int) (Math.random() * 100);
int boundary = 1 + (int) (Math.random() * 1000000);
res = find_numbers(x, y, boundary );
System.out.println(res);
}
}
Edit:
I wrote something after reading Shark's comment thank you so much. it's working.
import java.util.ArrayList;
public class Main {
public static ArrayList<Integer> find_numbers(int x, int y, int boundary) {
ArrayList<Integer> res = new ArrayList<Integer>();
int x_k = 0;
int y_k= 0;
while(Math.pow(x,x_k)< boundary){
x_k++;
}
while(Math.pow(y,y_k)< boundary){
y_k++;
}
for(int k = 2 ; k<= boundary;++k) {
for (int i = 0; i < x_k; ++i) {
for (int j = 0; j < y_k; ++j) {
if(k == (int)Math.pow(x,i)+(int)Math.pow(y,j) && !res.contains(k)){
System.out.println("----------------------------------------");
System.out.println(k +" =>" +x + "^" +i +"+"+y+ "^" +j);
res.add(k);
}
}
}
}
return res;
}
public static void main(String[] args) {
ArrayList<Integer> res = new ArrayList<Integer>();
int x = 1 + (int) (Math.random() * 100);
int y = 1 + (int) (Math.random() * 100);
int boundary = 1 + (int) (Math.random() * 1000000);
res = find_numbers(x, y,boundary);
System.out.println("x:" + x);
System.out.println("y:" + y);
System.out.println("boundary:" + boundary);
System.out.println("Result:" + res);
}
}
I am not sure if this is the most efficient method. Basically, I increment j until x^i + y^j > boundary then increment i.
public static ArrayList<Integer> findNumbers(int x, int y, int boundary) {
Set<Integer> result = new HashSet<>(); // make sure result is unique
int powerX = 0, powerY = 0, total = 0, tempX = 0;
while (true) {
// calculate x^i
tempX = (int) Math.pow(x, powerX);
while (true) {
// calculate x^i + y^j and compare against boundary
if ((total = tempX + (int) Math.pow(y, powerY)) <= boundary) {
// add result to set and increment y
result.add(total);
powerY++;
// break if y <= 1
if (y <= 1)
break;
} else
break;
}
// break if x <= 1 || x^i > boundary
if (tempX > boundary || x <= 1)
break;
// reset j and increment i
powerY = 0;
powerX++;
}
// return sorted result
ArrayList<Integer> arr = new ArrayList<>();
arr.addAll(result);
arr.sort(null);
return arr;
}
You might be able refactor the code for better efficiency.
public class Main {
public static ArrayList<Integer> find_numbers(int x, int y, int boundary) {
ArrayList<Integer> res = new ArrayList<Integer>();
int x_k = 0;
int y_k= 0;
while(Math.pow(x,x_k)< boundary){
x_k++;
}
while(Math.pow(y,y_k)< boundary){
y_k++;
}
for(int k = 2 ; k<= boundary;++k) {
for (int i = 0; i < x_k; ++i) {
for (int j = 0; j < y_k; ++j) {
if(k == (int)Math.pow(x,i)+(int)Math.pow(y,j) && !res.contains(k)){
System.out.println("----------------------------------------");
System.out.println(k +" =>" +x + "^" +i +"+"+y+ "^" +j);
res.add(k);
}
}
}
}
return res;
}
public static void main(String[] args) {
ArrayList<Integer> res = new ArrayList<Integer>();
int x = 1 + (int) (Math.random() * 100);
int y = 1 + (int) (Math.random() * 100);
int boundary = 1 + (int) (Math.random() * 1000000);
res = find_numbers(x, y,boundary);
System.out.println("x:" + x);
System.out.println("y:" + y);
System.out.println("boundary:" + boundary);
System.out.println("Result:" + res);
}
}
I created a program that generates a user inputted number of pairs of points. It then goes through a bruteforce and divide and conquer methods to find the closest pair of points. The bruteforce method works perfectly. The divide and conquer method on the other hand gives me an output but it is different than the brute force distance almost 90% of the time. I can't seem to figure out why it is like this in my code. NOTE: Some of the comments in the functions are from my teacher. Also, the closest_pair function along with rec_cl_pair have been given to me by my teacher where I must use them but had to adjust to my code (they were pseudo code for most part).
My code is:
import java.util.*;
import static java.lang.Math.min;
public class ClosestPair{
private Double x;
private Double y;
private static Double minDist = Double.POSITIVE_INFINITY;
private static ClosestPair closestPair1 = new ClosestPair(0.0,0.0);
private static ClosestPair closestPair2 = new ClosestPair(0.0,0.0);
public ClosestPair(Double x, Double y){
this.x = x;
this.y = y;
}
public static void main(String[] args) {
Double rangeMin = 0.0;
Double rangeMax = 1000.0;
Random r = new Random();
Scanner scan = new Scanner(System.in);
System.out.print("\nEnter the number of two dimensional arrays: ");
int dim = scan.nextInt();
ClosestPair[] pair = new ClosestPair[dim];
ClosestPair[] pairCopy = new ClosestPair[dim];
for(int i = 0; i < dim; i++){
Double xVal = rangeMin + (rangeMax - rangeMin) * r.nextDouble();
Double yVal = rangeMin + (rangeMax - rangeMin) * r.nextDouble();
pair[i] = new ClosestPair(xVal,yVal);
//System.out.print(pair[i].x + ", " + pair[i].y + "\n");
}
/*
for(int j = 0; j < pair.length; j++){
System.out.print(pair[j].x + ", " + pair[j].y + "\n");
}
*/
pairCopy = pair;
pair = mergeSort(pair);
/*
System.out.print("\n\n\n");
for(int j = 0; j < pair.length; j++){
System.out.print(pair[j].x + ", " + pair[j].y + "\n");
}
*/
//BRUTE FORCE PRINT STATEMENTS
long startTime = System.nanoTime();
bruteForce(pair);
long endTime = System.nanoTime();
long timeSpent = endTime - startTime;
System.out.print("\nMin Distance = " + minDist);
System.out.print("\n(x1,y1) = " + closestPair1.x + ", " + closestPair1.y);
System.out.print("\n(x2,y2) = " + closestPair2.x + ", " + closestPair2.y);
System.out.print("\nTime: " + timeSpent + "\n\n");
minDist = 0.0;
//CONQUER DIVIDE PRINT STATEMENTS
startTime = System.nanoTime();
minDist = closest_pair(pairCopy);
endTime = System.nanoTime();
timeSpent = endTime - startTime;
System.out.print("Min Distance = " + minDist);
System.out.print("\nTime: " + timeSpent);
scan.close();
}
private static void bruteForce(ClosestPair[] pair) {
for(int i = 1; i < pair.length - 1; i++){
for(int j = i + 1; j < pair.length; j++){
ClosestPair p = new ClosestPair(pair[i].x,pair[i].y);
//System.out.print("\np:" + pair[i].x + ", " + pair[i].y);
ClosestPair q = new ClosestPair(pair[j].x,pair[j].y);
//System.out.print("\nq: " + pair[j].x + ", " + pair[j].y);
if(getDistance(p, q) < minDist){
minDist = getDistance(p, q);
closestPair1.x = p.x;
closestPair1.y = p.y;
closestPair2.x = q.x;
closestPair2.y = q.y;
}
}
}
}
private static Double getDistance(ClosestPair p1, ClosestPair p2) {
double xdist = p2.x - p1.x;
double ydist = p2.y - p1.y;
return Math.hypot(xdist, ydist);
}
static ClosestPair[] mergeSort(ClosestPair[] a) {
if (a.length > 1) {
int q = a.length/2;
ClosestPair[] leftArray = Arrays.copyOfRange(a, 0, q);
ClosestPair[] rightArray = Arrays.copyOfRange(a,q,a.length);
mergeSort(leftArray);
mergeSort(rightArray);
a = merge(a,leftArray,rightArray);
}
return a;
}
static ClosestPair[] merge(ClosestPair[] a, ClosestPair[] l, ClosestPair[] r) {
int totElem = l.length + r.length;
//int[] a = new int[totElem];
int i,li,ri;
i = li = ri = 0;
while ( i < totElem) {
if ((li < l.length) && (ri<r.length)) {
if (l[li].x < r[ri].x) {
a[i] = l[li];
i++;
li++;
}
else {
a[i] = r[ri];
i++;
ri++;
}
}
else {
if (li >= l.length) {
while (ri < r.length) {
a[i] = r[ri];
i++;
ri++;
}
}
if (ri >= r.length) {
while (li < l.length) {
a[i] = l[li];
li++;
i++;
}
}
}
}
return a;
}
//START OF CONQUER DIVIDE SECTOIN
static double closest_pair(ClosestPair[] p){
int n = p.length - 1;
p = mergeSortDC(p, 0, n); // sort all n points by x-coordinate
return rec_cl_pair(p, 0, n);
}
static double rec_cl_pair(ClosestPair[] p, int i, int j){ // finds closest pair between points in p[i..j]
// assumes input is sorted by x-coordinate
// at termination, input is sorted by y-coordinate
// i is the left index of the subarray, j is the right index
if (j - i < 3){ // at most 3 points in p[i..j]
p = mergeSortDC (p, i, j); // sort p[i..j] by y-coordinate
double delta = getDistance(p[i], p[i+1]);
if (j - i == 1) { // two points
minDist = delta;
return delta;
}
else{
double min1 = min(getDistance(p[i+1], p[i+2]), getDistance(p[i], p[i+2]));
minDist = min(delta,min1);
return minDist;
}
}
int m = (i + j)/2;
double line = p[m].x;
double deltaL = rec_cl_pair(p, i, m); // p[i..m] is sorted by y-coordinate
double deltaR = rec_cl_pair(p, m+1, j); // p[m+1..j] is sorted by y-coordinate
double delta = min(deltaL, deltaR);
p = mergeDC(p, i, m, j); // p[i..j] is now sorted by y-coordinate
// Of points in p[i..j], find points in vertical strip of width 2*delta,
// centered at line (middle of x-values), and store in array v
int t = 0;
ClosestPair[] v = new ClosestPair[j+1];
for(int k = i; k < j; k++){
if ((p[k].x > line - delta) && (p[k].x < line + delta)){
t = t + 1;
v[t] = p[k];
}
}
// Find closest pairs among points in array v. NOTE: Cool math shows
// there are at most 8 points in the strip at distance < delta. Thus,
// in the loops below, each point is compared to at most 7 other points.
for(int k = 1;k < t-1; k++){
for(int s = k+1; k < min(t,k+7); s++){ // inner loop iterates <= 7 times
delta = min(delta, getDistance(v[k],v[s]));
minDist = delta;
return delta;
}
}
return minDist;
}
private static ClosestPair[] mergeSortDC(ClosestPair[] p, int low, int high) {
// check if low is smaller then high, if not then the array is sorted
if (low < high) {
// Get the index of the element which is in the middle
int middle = low + (high - low) / 2;
// Sort the left side of the array
mergeSortDC(p, low, middle);
// Sort the right side of the array
mergeSortDC(p, middle + 1, high);
// Combine them both
p = mergeDC(p, low, middle, high);
}
return p;
}
private static ClosestPair[] mergeDC(ClosestPair[] p, int low, int middle, int high) {
ClosestPair[] helper = new ClosestPair[p.length];
// Copy both parts into the helper array
for (int i = low; i <= high; i++) {
helper[i] = p[i];
}
int i = low;
int j = middle + 1;
int k = low;
// Copy the smallest values from either the left or the right side back
// to the original array
while (i <= middle && j <= high) {
if (helper[i].x <= helper[j].x) {
p[k] = helper[i];
i++;
} else {
p[k] = helper[j];
j++;
}
k++;
}
// Copy the rest of the left side of the array into the target array
while (i <= middle) {
p[k] = helper[i];
k++;
i++;
}
return p;
}
}
An example of output is:
Enter the number of two dimensional arrays: 50
Min Distance = 19.014027210555614
(x1,y1) = 76.99595098629398, 600.1657767818473
(x2,y2) = 87.04091889578226, 616.3098732403395
Time: 3852815
Min Distance = 29.457199999686082
Time: 414081
The first min distance is the bruteforce result. The second is the divide and conquer result
I'm trying to write a code that multiplies two strings of integers. I'm not too sure where it's going wrong... It works for some numbers, but is horribly wrong for others. I'm not asking for a full solution, but just a hint (I seriously appreciate any help possible) as to where I'm making the obviously silly mistake. Thanks in advance.
public static void main(String[] args) {
Scanner scan = new Scanner(System.in);
System.out.print("Please enter a big integer. ");
String t = scan.nextLine();
System.out.print("And another. ");
String s = scan.nextLine();
BigInt a = new BigInt(t);
BigInt b = new BigInt(s);
System.out.println(a + " + " + b + " = " + a.add(b));
System.out.println(a + " - " + b + " = " + a.sub(b));
System.out.println(a + " * " + b + " = " + a.mul(b));
System.out.println(a + " / " + b + " = " + a.div(b));
}
}
class BigInt {
public BigInt() {
n = new int[1];
}
public BigInt(String s) {
n = new int[s.length()];
for (int i = 0; i < n.length; ++i) {
n[n.length - i - 1] = s.charAt(i) - '0' ;
}
}
private BigInt(int[] n) {
this.n = new int[n.length];
for (int i = 0; i < n.length; ++i) {
this.n[i] = n[i];
}
}
public String toString() {
String s = "";
for (int i : n) {
s = i + s;
}
return s;
}
public BigInt mul(BigInt o) {
int carry = 0;
int s = 0;
int digit;
int subtotal = 0;
int total = 0;
int max = n.length > o.n.length ? n.length : o.n.length;
int[] result = new int[n.length + o.n.length];
for (int i = 0; i < o.n.length; ++i) {
int bottom = i <= o.n.length ? o.n[i] : 0;
for (s = 0; s <= n.length; ++s){
int top = s < n.length ? n[s] : 0;
int prod = (top * bottom + carry);
if (s == (max-1)) {
total = Integer.valueOf((String.valueOf(prod) + String.valueOf(subtotal)));
carry = 0;
digit = 0;
subtotal = 0;
break;
}
if (prod < 10) {
digit = prod;
subtotal += digit;
carry = 0;
}
if (prod >= 10); {
digit = prod % 10;
carry = prod / 10;
subtotal += digit;
}
}
result[i] = total;
}
return new BigInt(trim(result));
}
private int[] trim(int[] nums) {
int size = nums.length;
for (int i = nums.length - 1; i > 0; --i) {
if (nums[i] != 0) {
break;
}
--size;
}
int[] res = new int[size];
for (int i = 0; i < size; ++i) {
res[i] = nums[i];
}
return res;
}
private int[] n;
}
A quick test using:
for (int x = 0; x < 10; x++) {
for (int y = 0; y < 10; y++) {
System.out.println(x + " * " + y + " = " + new BigInt(Integer.toString(x)).mul(new BigInt(Integer.toString(y))));
}
}
demonstrates that somehow your multiply of x * y is actually multiplying by 10x * y. That should give you a clear hint to the problem.
I need some help in this program. I have the whole program done and set. I am having trouble in the printf statement as everytime I run the program, I get an IllegalFormatConversionException error even though the program compiles flawlessly.
This is the printf in question:
System.out.printf("%s%20d%10d%10.1f", "Average", categoryAvg, pressureAvg, speedMPHAvg);
Code:
import java.util.Scanner;
import java.io.File;
import java.io.IOException;
public class Hurricanes2
{
public static void main(String[] args) throws IOException
{
int arrayLength = 59;
int [] year = new int[arrayLength];
String [] month = new String[arrayLength];
int [] pressure = new int[arrayLength];
int [] speed = new int[arrayLength];
String [] name = new String[arrayLength];
double [] speedMPH = new double[arrayLength];
int [] category = new int[arrayLength];
int c1 = 0;
int c2 = 0;
int c3 = 0;
int c4 = 0;
int c5 = 0;
int categoryMin = 0;
int categoryMax = 0;
int speedMin = 0;
int speedMax = 0;
int pressureMin = 0;
int pressureMax = 0;
int categorySum = 0;
int speedMPHSum = 0;
int pressureSum = 0;
double categoryAvg = 0;
double speedMPHAvg = 0;
double pressureAvg = 0;
File fileName = new File("hurcdata2.txt");
Scanner inFile = new Scanner(fileName);
int index = 0;
while (inFile.hasNext())
{
year[index] = inFile.nextInt();
month[index] = inFile.next();
pressure[index] = inFile.nextInt();
speed[index] = inFile.nextInt();
name[index] = inFile.next();
index++;
}
inFile.close();
for(index = 0; index < arrayLength; index++)
{
speedMPH [index] = (speed[index]) * 1.15;
if(speedMPH[index] >= 74 && speedMPH[index] <= 95)
{
category[index] = 1;
c1++;
}
else if(speedMPH[index] >= 96 && speedMPH[index] <= 110)
{
category[index] = 2;
c2++;
}
else if(speedMPH[index] >= 111 && speedMPH[index] <= 130)
{
category[index] = 3;
c3++;
}
else if(speedMPH[index] >= 131 && speedMPH[index] <= 155)
{
category[index] = 4;
c4++;
}
else
{
category[index] = 5;
c5++;
}
}
for(index = 0; index < arrayLength; index++)
{
categoryMin = category[index];
if(category[index] < categoryMin)
{
category[index] = categoryMin;
}
categoryMax = category[index];
if(category[index] > categoryMax)
{
category[index] = categoryMax;
}
speedMin = speed[index];
if(speed[index] < speedMin)
{
speed[index] = speedMin;
}
speedMax = speed[index];
if(speed[index] > speedMax)
{
speed[index] = speedMax;
}
pressureMin = pressure[index];
if(pressure[index] < pressureMin)
{
pressure[index] = pressureMin;
}
pressureMax = pressure[index];
if(pressure[index] > pressureMax)
{
pressure[index] = pressureMax;
}
categorySum += category[index];
speedMPHSum += speedMPH[index];
pressureSum += pressure[index];
}
categoryAvg = (double)categorySum / arrayLength;
speedMPHAvg = (double)speedMPHSum / arrayLength;
pressureAvg = (double)pressureSum / arrayLength;
System.out.printf("%40s", "Hurricanes 1980 - 2006");
System.out.println();
System.out.println();
System.out.printf("%s%10s%10s%10s%10s", "Year", "Hurricane", "Category", "Pressure (mb)", "Wind Speed (mph)");
System.out.println();
System.out.println("=====================================================================");
for(index = 0; index < arrayLength; index++)
{
System.out.printf("%d%10s%10d%10d%10f", year[index], name[index], category[index], pressure[index], speedMPH[index]);
System.out.println();
}
System.out.println("=====================================================================");
System.out.println();
System.out.printf("%s%20d%10d%10.1f", "Average", categoryAvg, pressureAvg, speedMPHAvg);
System.out.println();
System.out.printf("%s%20d%10d%10.1f", "Maximum", categoryMax, pressureMax, speedMax);
System.out.println();
System.out.printf("%s%20d%10d%10.1f", "Minimum", categoryMin, pressureMin, speedMin);
System.out.println();
System.out.println("Number of Category 1 Hurricanes: " + c1);
System.out.println("Number of Category 2 Hurricanes: " + c2);
System.out.println("Number of Category 3 Hurricanes: " + c3);
System.out.println("Number of Category 4 Hurricanes: " + c4);
System.out.println("Number of Category 5 Hurricanes: " + c5);
}//end main()
}//end Hurricanes2
In printf, d is for integral types only, i.e. byte, short, int and long, not double.
Since categoryAvg and pressureAvg are double's, use f for them instead.
System.out.printf("%s%20f%10f%10.1f", "Average", categoryAvg, pressureAvg, speedMPHAvg);
And similarly f is not for int.
So, since speedMax and speedMin are int's, you should use d there instead:
System.out.printf("%s%20d%10d%10d", "Maximum", categoryMax, pressureMax, speedMax);
System.out.printf("%s%20d%10d%10d", "Minimum", categoryMin, pressureMin, speedMin);
(or change the types of your variables appropriately).
I need to use comb filter/transform to detect fundamental frequency of a wav file in java.
I also needed to implement ZCR, but this was easy.
Now I have this:
int best = 0, best_step = 0;
for (int step = 3; step < 400; ++step) {
int sum = 0;
for (i = 1; i < 10 && i * step < spectrum.length; ++i) {
for (int di = 0; di < i; ++di) {
sum += spectrum[i * step + di] / i;
}
}
sum *= 100;
comb.add(sum);
}
int sum = 0;
for (i = 0; i < comb.size(); ++i) {
sum = comb.get(i); // 3 * comb[i] - comb[i-1] - comb[i+1];
System.out.println(i + " - " + sum);
if (sum > best) {
best_step = i;
best = sum;
}
}
And my problem is that this code detects the wrong frequency. ;( I have searched for an algorithm/implementation (in any language) but have not found anything.
Note, I cannot use autocorelation, etc.. It must be comb filtering.
Edit: A little more explanation of my code:
I load a wav file and put frames to array frames. Then I make fft on it and have array of Complex (named widmo) (simple structure to handle complex numbers).
Now I put abs of Complex numbers into array spectrum:
double[] spectrum = new double[widmo.length];
for (i = 0; i + 1 < widmo.length; ++i) {
spectrum[i] = widmo[i].abs();
}
ArrayList<Integer> comb = new ArrayList<Integer>();
int best = 0, best_step = 0;
for (int step = 3; step < 400; ++step) {
int sum = 0;
for (i = 1; i < 10 && i * step < spectrum.length; ++i) {
for (int di = 0; di < i; ++di) {
sum += spectrum[i * step + di] / i;
}
}
// sum /= step + 100; // ta linijka pozwala usunąć sporo
// niespodziewanych skoków częstotliwości
sum *= 100;
comb.add(sum);
}
int sum = 0;
for (i = 0; i < comb.size(); ++i) {
sum = comb.get(i); // 3 * comb[i] - comb[i-1] - comb[i+1];
// ctx.fillRect(i, canvas.height, 1, -sum);
System.out.println(i + " - " + sum);
// tmp.add(new freqTime(sum,));
if (sum > best) {
best_step = i;
best = sum;
}
}
System.out.println();
System.out.println(best_step);
System.out.println(4 * 44100);
System.out.println((frames.length / numChanels));
System.out.println(best_step * 44100
/ (frames.length / numChanels));
The last println should show me my fundamental frequency, but it doesn't,.
I got this in javascript from my friend.
I figure it out (i think:P). Last println gives basic freq :). Maybe someone will need it or even imporve it :)
ArrayList<double[]> okna = new ArrayList<>();
ArrayList<freqTime> lista = new ArrayList<freqTime>();
int po2 = (int) Math.pow(2,
Integer.parseInt((String) potega2Input.getText()));
po2 /= 2;
double[] triangles = new double[po2];
double maxWykres = 0;
int licznik = 0;
int licznik2 = 0;
int T = frames.length;
boolean wykresFlaga = false;
for (int k = 0; k < T; k += po2) {
licznik = 0;
licznik2 = 0;
double[] tmp = new double[po2];
Complex[] zespolone = new Complex[po2];
for (int i = k; i < k + po2; i++) {
if (i < T) {
tmp[licznik] = frames[i];
zespolone[licznik] = new Complex(frames[i], 0);
licznik2 = licznik;
} else {
tmp[licznik] = frames[licznik2];
zespolone[licznik] = zespolone[licznik2];
}
licznik++;
}
okna.add(tmp);
FFT fft = new FFT();
zespolone = fft.fft(zespolone);
double maxF = 0;
double maxFI = 0;
double maxH = findMaxComp(zespolone);
double[] doWykresu = new double[zespolone.length];
for (int a = 2; a < 100; a++) {
for (int i = 0; i < po2; i++) {
doWykresu[i] = zespolone[i].abs();
triangles[i] = Math.abs(i % (2 * a) - a)
* (maxH) / a;
// triangles[i] = Math.abs(i % (2 * a) - a) * (maxH)
// / a;
}
double sumT = 0;
for (int i = 0; i < po2 / 2; i++) {
sumT += triangles[i] * doWykresu[i];
}
if (sumT > maxF) {
maxF = sumT;
maxFI = a;
}
}
//
// maxFI /= 2;
//
if (wykresFlaga == false) {
maxWykres = maxH;
}
for (int i = 0; i < po2; i++) {
doWykresu[i] = zespolone[i].abs();
triangles[i] = Math.abs(i % (2 * maxFI) - maxFI)
* (maxWykres) / maxFI;
}
if (wykresFlaga == false) {
System.out.println("Max w widmie: " + maxWykres);
new Wykres(doWykresu, 1, triangles);
wykresFlaga = true;
}
// System.out.println((2 * 44100 / po2) * maxFI);
System.out.println((float) (44100 / (float) po2)
* 2*(float) maxFI + " Znalzione a: " + maxFI);
lista.add(new freqTime(
(int) ((float) (44100 / (float) po2) *2* (float) maxFI),
(double) ((double) po2 / 44100)));
/*
* System.out.println((44100 / po2) * maxFI + " " + maxFI +
* " " + maxFI / 44100 + " " + 44100 / (maxFI / po2 * 44100)
* + " " + 44100 * maxFI / T);
*/
// System.out.println(zespolone[(int) maxFI/2].abs());
}