Splitting a swing control into equal parts - java

I know this is gonna be a stupid question.
Pardon me as a n00b into CS
I have a new swing component that inherits from JComponent.
I am trying to paint lines on its surface to show that the lines split the control into equal parts. The code looks like
int spc;
spc = (int) Math.round((this.ZBar.getWidth() / this.ZBar.getModel().getModelSize()));
for (int i = 0; i <= this.ZBar.getModel().getModelSize(); i++) {
g.drawLine(i * spcing, 0, i *, this.ZBar.getHeight());
}
this.ZBar.getModel().getModelSize(); gives out number of parts to split into.
However, in some cases there is some more space left on the right most end of my component. I guess it is gue to the Type conversion done by Math.round. How can I solve this ??

It is because that division is a int type divide. For example:
5 / 2 == 2
Math.round is doing nothing here. It is already being rounded (as Math.floor instead).
To get your intended effect, cast the int to a double before the division:
(double)5 / 2 == 2.5
Or in your specific case:
spc = (int) Math.round(((double)this.ZBar.getWidth() / this.ZBar.getModel().getModelSize()));

The code you posted will not compile due to syntax errors, but I see no immediate problems with your approach. You said that the problem shows up intermittendly. This suggests the problem might lay with the way swing does refreshing, and how you handle that in your code. Try reading up on that.

Thank you very much for the reply.
Solved this.
I have made all those integer mess to double.
Then used Java2D package to handle doubles.
Line2D class support creation using double parameters.

Related

dealing with negative square roots in android

I am working on a function plotter project for Android in which the user inputs the equation as a string.
this string is solved using the EvalEx library and I get a bunch of data points which I plot using graph-view library.
now the problem is when I give it an equation with negative square root. for example SQRT(1-x) this is causing errors.
for( i = 0; i < x.length ; i++) {
//the equation solver only takes BigDecimal as input.
x1 = new BigDecimal(x[i]);
try {
// eq is the sting that i got from the EditText.
y1 = new Expression(eq).with("x", x1).eval();
y[i] = y1.floatValue();
} catch(ArithmeticException excp) {
//these are the data points that go into the plot function
x[i] = 0;
y[i] = 0;
}
}
I'm still a little unclear what you are trying to do, but I think I understand enough to give you a definitive answer.
Here's the thing:
The eval(...) function returns a single value.
That's what the API says. That's all it can do. You cannot avoid that fact. (There is no magic .....)
So if you want to get both (real) square roots, you need take the positive result returned by SQRT and negate it yourself to get the second solution. In your code. Something like this:
y1 = new Expression("SQRT(3 - x^2)").with("x", x1).eval();
y2 = BigDecimal.ZERO - y1;
Of course, this is special-case code1. And there is no general-case code that is going to give you multiple solutions to equations when the SQRT functions could be anywhere in your expression.
And expressions with complex solutions will be even more intractable with the EvalEx API. You cannot represent a complex solution using the (single) BigDecimal that is returned by the eval method. (If you look at the code, taking a square root of a negative number throws the API's ExpressionException.)
The bottom line is that EvalEx is a simple, light-weight expression evaluator. It is not designed for your use-case which involves finding all solutions, and / or dealing with complex numbers. And making the existing API work for these use-cases would be ... impossible.
But the good news is that the source code for EvalEx is available on GitHub.
https://github.com/uklimaschewski/EvalEx (I assume this is corresponds to the version you are using.)
You could download it and use it as the starting point for writing a more sophisticated expression evaluator.
Or ... you could look for an alternative library that does what you need.
1 - That is, it is implemented with the pre-knowledge of what the expression we are evaluating is! Moreover, it still fails for values of x where 3 - x^2 is negative.

The same (int)doubles round up and down in Java

I'm having the weirdest problem with my game in java. :|
I can get around it, so I will be able to continue on this game without a solution, but I just thought it was really weird.
It's a 2D Minecraft-ish (I know, I know, it's just for practice) game, and I'm trying to destroy blocks by clicking them, which is working, but not as expected.
mX = (x * blockWidth - screenWidth * blockWidth / 2 + blockWidth / 2 + e.getX()) / blockWidth;
mY = y - screenHeight / 2 + .5 + e.getY() / blockHeight;
These two lines should define the x and y coordinates of the block the mouse is currently hovering over. Filling in the same numbers will result in the same answer as the second formula is a shorter version of the first. However, the second one does not work, clicking a block in the upper half section will result in breaking the block above it. The only reason I can think of is that, in the mouseClicked() method, the (int) (which is required as you can't click on half coordinates) rounds the first one up and the second one down because of the .5 in it. I'm not sure, that's why I'm asking you. :)
Does anyone know what the cause of this might be? I prefer not to use the upper formula because I want it to be much simpler.
Java is doing some hidden casts. Depending on which variable is a double or an int, you might get unexpected results because some double values have been casted to ints. I would make sure all your variables are doubles.
Also, do not forget that floating points also have representation limitations, that can affect computation and computation results.
If you want to round your value, you can use:
Math.round(2.7);
if you want to "round up", you can use:
Math.ceil(2.7);
if you want to "round down", you can use:
Math.floor(2.7);

Sum to determine the largest multiple of 5 under 1,000

I am currently trying to get a feature working in a Java application I am making, however I'm uncertain how to implement this in a single line.
I know that I could do something along the lines of (not exactly, but roughly):
while(i<995){
i=i+5
}
However I am eager to implement this all into one line, such as in a single
static int highestMult = *the equation*
I would not be using this specifically for the highest multiple of 5 in 1,000, however upon my own research I could not find a desired solution for this specific case, therefore this is an example.
The examples I have previously found all, generally, relate to finding only a highest multiple, not putting together the highest multiple, and a limit.
If this is not knowledge from the back of your head, it'd also be a great help just to understand the logic behind how you came up with the solution, it could save me being stuck on similar issues in the future.
Thanks,
If c is the under number (1000 in your case), and m the multiple (5 in your case), then
((c - 1) / m) * m
is one way. (Note to purists: you don't actually need the outer parentheses but I include them for clarity).
Here I'm exploiting integer arithmetic to force the truncation of ((c - 1) / m) to the flooring integer. Multiplication of this result by m means the final value is a multiple of m. Make sure that c and m are integral types or this will not work (unless you cast explicitly which is not as elegant).
This is undefined for c < 1 and m < 1
try:
int number=5;
int limit=999;
int i=limit-(limit%number);
where 999 is limit - 1
% is reminder
(999%5)=4
if we remove the reminder from limit, we will got it:
999-4=995
we could use limit=1000, but result could be 1000 too
reminder is very useful thing for programming :D
defined for number > 0 and limit >=0

Calculate exact area under curve in Java

Are there any methods which do that? I have an application where I need the area under the curve, and I am given the formula, so if I can do the integration on hand, I should be able to do it programatically? I can't find the name of the method I'm referring to, but this image demonstrates it: http://www.mathwords.com/a/a_assets/area%20under%20curve%20ex1work.gif
Edit: to everyone replying, I have already implemented rectangular, trapezoidal and Simpson's rule. However, they take like 10k+ stripes to be accurate, and should I not be able to find programatically the integrated version of a function? If not, there must be a bloody good reason for that.
Numerical integration
There are multiple methods, which can be used. For description, have a look in Numerical Recipes: The Art of Scientific Computing.
For Java there is Apace Commons library, which can be used. Integration routines are in Numerical Analysis section.
Symbolic integration
Check out jScience. Functions module "provides support for fairly simple symbolic math analysis (to solve algebraic equations, integrate, differentiate, calculate expressions, and so on)".
If type of function is given, it can be possible to integrate faster in that specific case than when using some standard library.
To compute it exactly, you would need a computer algebra system library of some sort to perform symbolic manipulations. Such systems are rather complicated to implement, and I am not familiar with any high quality, open source libraries for Java. An alternative, though, assuming it meets your requirements, would be to estimate the area under the curve using the trapezoidal rule. Depending on how accurate you require your result to be, you can vary the size of the subdivisions accordingly.
I would recommend using Simpsons rule or the trapezium rule, because it could be excessively complicated to integrate every single type of graph.
See Numerical analysis specifically numerical integration. How about using the Riemann sum method?
You can use numerical integration, using some rule, like already mentioned Simpsons, Trapezoidal, or Monte-Carlo simulation. It uses pseudo random generator.
You can try some libraries for symbolic integration, but I'm not sure that you can get symbolic representation of every integral.
Here's a simple but efficient approach:
public static double area(DoubleFunction<Double> f, double start, double end, int intervals) {
double deltaX = (end - start)/intervals;
double area = 0.0;
double effectiveStart = start + (deltaX / 2);
for (int i=0; i<intervals; ++i) {
area += f.apply(effectiveStart + (i * deltaX));
}
return deltaX * area;
}
This is a Riemann sum using the midpoint rule, which is a variation of the trapezoidal rule, except instead of calculating the area of a trapezoid, I use a rectangle from f(x) at the middle of the interval. This is faster and gives a better result. This is why my effective starting value of x is at the middle of the first interval. And by looping over an integer, I avoid any round-off problems.
I also improve performance by waiting till the end of the loop before multiplying by deltaX. I could have written the loop like this:
for (int i=0; i<intervals; ++i) {
area += deltaX * f.apply(effectiveStart + (i * deltaX)); // this is x * y for each rectangle
}
But deltaX is constant, so it's faster to wait till the loop is finished.
One of the most popular forms of numeric integration is the Runge-Kutta order 4 (RK4) technique. It's implementations is as follows:
double dx, //step size
y ; //initial value
for(i=0;i<number_of_iterations;i++){
double k1=f(y);
double k2=f(y+dx/2*k1);
double k3=f(y+dx/2*k2);
double k4=f(y+dx*k3);
y+= dx/6*(k1+2*k2+2*k3+k4);
}
and will converge much faster than rectangle, trapezoids, and Simpson's rule. It is one of the more commonly used techniques for integration in physics simulations.

Java Array Manipulation

I have a function named resize, which takes a source array, and resizes to new widths and height. The method I'm using, I think, is inefficient. I heard there's a better way to do it. Anyway, the code below works when scale is an int. However, there's a second function called half, where it uses resize to shrink an image in half. So I made scale a double, and used a typecast to convert it back to an int. This method is not working, and I dont know what the error is (the teacher uses his own grading and tests on these functions, and its not passing it). Can you spot the error, or is there a more efficient way to make a resize function?
public static int[][] resize(int[][] source, int newWidth, int newHeight) {
int[][] newImage=new int[newWidth][newHeight];
double scale=newWidth/(source.length);
for(int i=0;i<newWidth/scale;i++)
for(int j=0;j<newHeight/scale;j++)
for (int s1=0;s1<scale;s1++)
for (int s2=0;s2<scale;s2++)
newImage[(int)(i*scale+s1)][(int)(j*scale+s2)] =source[i][j];
return newImage;
}
/**
* Half the size of the image. This method should be just one line! Just
* delegate the work to resize()!
*/
public static int[][] half(int[][] source) {
int[][] newImage=new int[source.length/2][source[0].length/2];
newImage=resize(source,source.length/2,source[0].length/2);
return newImage;
}
So one scheme for changing the size of an image is to resample it (technically this is really the only way, every variation is really just a different kind of resampling function).
Cutting an image in half is super easy, you want to read every other pixel in each direction, and then load that pixel into the new half sized array. The hard part is making sure your bookkeeping is strong.
static int[][] halfImage(int[][] orig){
int[][] hi = new int[orig.length/2][orig[0].length/2];
for(int r = 0, newr = 0; r < orig.length; r += 2, newr++){
for(int c = 0, newc = 0; c < orig[0].length; c += 2, newc++){
hi[newr][newc] = orig[r][c];
}
}
return hi;
}
In the code above I'm indexing into the original image reading every other pixel in every other row starting at the 0th row and 0th column (assuming images are row major, here). Thus, r tells us which row in the original image we're looking at, and c tells us which column in the original image we're looking at. orig[r][c] gives us the "current" pixel.
Similarly, newr and newc index into the "half-image" matrix designated hi. For each increment in newr or newc we increment r and c by 2, respectively. By doing this, we skip every other pixel as we iterate through the image.
Writing a generalized resize routine that doesn't operate on nice fractional quantities (like 1/2, 1/4, 1/8, etc.) is really pretty hard. You'd need to define a way to determine the value of a sub-pixel -- a point between pixels -- for more complicated factors, like 0.13243, for example. This is, of course, easy to do, and you can develop a very naive linear interpolation principle, where when you need the value between two pixels you simply take the surrounding pixels, construct a line between their values, then read the sub-pixel point from the line. More complicated versions of interpolation might be a sinc based interpolation...or one of many others in widely published literature.
Blowing up the size of the image involves something a little different than we've done here (and if you do in fact have to write a generalized resize function you might consider splitting your function to handle upscaling and downscaling differently). You need to somehow create more values than you have originally -- those interpolation functions work for that too. A trivial method might simply be to repeat a value between points until you have enough, and slight variations on this as well, where you might take so many values from the left and so many from the right for a particular position.
What I'd encourage you to think about -- and since this is homework I'll stay away from the implementation -- is treating the scaling factor as something that causes you to make observations on one image, and writes on the new image. When the scaling factor is less than 1 you generally sample from the original image to populate the new image and ignore some of the original image's pixels. When the scaling factor is greater than 1, you generally write more often to the new image and might need to read the same value several times from the old image. (I'm doing a poor job highlighting the difference here, hopefully you see the dualism I'm getting at.)
What you have is pretty understandable, and I think it IS an O(n^4) algorithm. Ouchies!
You can improve it slightly by pushing the i*scale and j*scale out of the inner two loops - they are invariant where they are now. The optimizer might be doing it for you, however. There are also some other similar optimizations.
Regarding the error, run it twice, once with an input array that's got an even length (6x6) and another that's odd (7x7). And 6x7 and 7x6 while you're at it.
Based on your other question, it seems like you may be having trouble with mixing of types - with numeric conversions. One way to do this, which can make your code more debuggable and more readable to others not familiar with the problem space, would be to split the problematic line into multiple lines. Each minor operation would be one line, until you reach the final value. For example,
newImage[(int)(i*scale+s1)][(int)(j*scale+s2)] =source[i][j];
would become
int x = i * scale;
x += s1;
int y = j* scale;
y +=s2;
newImage[x][y] = source[i][j];
Now, you can run the code in a debugger and look at the values of each item after each operation is performed. When a value doesn't match what you think it should be, look at it and figure out why.
Now, back to the suspected problem: I expect that you need to use doubles somewhere, not ints - in your other question you talked about scaling factors. Is the factor less than 1? If so, when it's converted to an int, it'll be 0, and you'll get the wrong result.

Categories