Let's say I have a simple line chart with 5 values (a = 155, b = 200, c = 250, d = 300, e 0 345)
I need a way to calculate which values go on the Y-axis, in such a way that the values look nice. I also want to see the minor steps.
If I use a simple formula I would do this:
MaxValue - Minvalue = difference
300- 900 = 600
For 5 steps: 600/5 = 120 per step
That would lead to these values for the Y-axis:
Y0 = 200.0 (Rounding off to 200)
Y1 = 360.0 (Rounding off to 400)
Y2 = 520.0 (Rounding off to 600)
Y3 = 680.0 (Rounding off to 700)
Y4 = 840.0 (Rounding off to 900)
Y4 = 1000.0 (Rounding off to 1000)
What I actually would like is the values to be:
Y0 = 200
Y1 = 400
Y2 = 600
Y3 = 800
Y4 = 1000
But how do I calculate this?
Before calculation I don't know the magnitude of the values, it could be also like thousands, or tens.
Not exactly what you expect, but may give you an idea:
const int N = 6;
double vals[N] = {200.0, 360.0, 520.0, 680.0, 840.0, 1000.0};
for (int i = 0; i < N; i++) {
double factor = pow(10.0, floor(log10(vals[i])));
double v = floor(vals[i] / factor + 0.5) * factor;
std::cout << vals[i] << " " << v << std::endl;
}
P.S. Sorry, it's in C++ but you can easily translate it to Java.
Related
I'm working on some software that's for performance tuning Subaru's. The software takes logged parameters from the vehicle, graphs it on a scatter plot against the X axis (engine RPM), and allows for drag/drop adjustment. The adjustments are made on a 2D table with an X and Y axis that looks similar to something like this: https://imgur.com/a/PwDXevu
In order to get the most precise adjustments, I first find the value on the table with the logged X/Y values (in this case, it's engine load and engine RPM) and then use bilinear interpolation to find the exact value. What I would like to accomplish is take said value, increase or decrease the value and then reverse the process adjusting all four cells accordingly to reflect the changes. I could increase/decrease all four cells equally by the difference and it will result in the correct value, but what I actually want is to adjust each of the four cells according to where the X and Y lands.
example using the attached table:
x0 = 2.00
x1 = 2.30
y0 = 2400
y1 = 2800
x0y0 = 18.67
x0y1 = 19.38
x1y0 = 16.56
x1y1 = 17.62
Logged_X = 2.15
Logged_Y = 2600
the bilinear interpolation value would be: 18.0575
A simpler example would be:
| 1 | 2 |
---------
400 | 4 | 6 |
800 | 6 | 8 |
x0 = 1
x1 = 2
y0 = 400
y1 = 800
x0y0 = 4
x0y1 = 6
x1y0 = 6
x1y1 = 8
Logged_X = 1
Logged_Y = 400
the bilinear interpolation value would be: 4
In the first example, if I wanted the new bilinear interpolation value to be 19.00, it's obvious I would increase all four cell values by the difference (0.9425) because the X/Y fall directly in the center, and all four cells equally contribute to the value. In the second example, 100% of the bilinear interpolation value comes from the x0y0 cell, so I would like 100% of the adjustment to go towards that cell.
Unfortunately most logged X/Y values will not fall into one of these two examples and will more than likely fall somewhere in between.
I'm looking for a streamlined approach to this. Any help is greatly appreciated.
The following is the code used currently:
public double test(JTable table, double xVal, double yVal, double oldVal, double newVal) {
double x0, x1, y0, y1, x0y0, x1y0, x0y1, x1y1, originalval, xCellVal, yCellVal;
int x0Idx, x1Idx, y0Idx, y1Idx;
ArrayList<Double> xAxisArray = getAxisData(table, 0);
ArrayList<Double> yAxisArray = getAxisData(table, 1);
int xIdx = Utils.closestValueIndex(xVal, xAxisArray);
int yIdx = Utils.closestValueIndex(yVal, yAxisArray);
xCellVal = xAxisArray.get(xIdx);
if (xVal < xCellVal) {
x1Idx = xIdx;
x1 = xCellVal;
if (xIdx > 0) {
x0Idx = xIdx - 1;
x0 = xAxisArray.get(x0Idx);
}
else {
x0Idx = x1Idx;
x0 = x1;
}
}
else if (xVal > xCellVal) {
x0Idx = xIdx;
x0 = xCellVal;
if (xIdx < xAxisArray.size() - 1) {
x1Idx = xIdx + 1;
x1 = xAxisArray.get(x1Idx);
}
else {
x1Idx = x0Idx;
x1 = x0;
}
}
else {
x0Idx = x1Idx = xIdx;
x0 = x1 = xCellVal;
}
yCellVal = yAxisArray.get(yIdx);
if (yVal < yCellVal) {
y1Idx = yIdx;
y1 = yCellVal;
if (yIdx > 0) {
y0Idx = yIdx - 1;
y0 = yAxisArray.get(y0Idx);
}
else {
y0Idx = y1Idx;
y0 = y1;
}
}
else if (yVal > yCellVal) {
y0Idx = yIdx;
y0 = yCellVal;
if (yIdx < yAxisArray.size() - 1) {
y1Idx = yIdx + 1;
y1 = yAxisArray.get(y1Idx);
}
else {
y1Idx = y0Idx;
y1 = y0;
}
}
else {
y0Idx = y1Idx = yIdx;
y0 = y1 = yCellVal;
}
x0y0 = Double.valueOf(table.getValueAt(y0Idx + 1, x0Idx + 1).toString());
x1y0 = Double.valueOf(table.getValueAt(y0Idx + 1, x1Idx + 1).toString());
x0y1 = Double.valueOf(table.getValueAt(y1Idx + 1, x0Idx + 1).toString());
x1y1 = Double.valueOf(table.getValueAt(y1Idx + 1, x1Idx + 1).toString());
return Utils.bilinearInterpolation(xVal, yVal, x0, x1, y0, y1, x0y0, x0y1, x1y0, x1y1);
}
public static double bilinearInterpolation(double x, double y, double x0, double x1, double y0, double y1, double x0y0, double x0y1, double x1y0, double x1y1) {
double t1, t2;
if (y1 == y0) {
t1 = x0y0;
t2 = x1y0;
}
else {
t1 = (y - y0) * (x0y1 - x0y0) / (y1 - y0) + x0y0;
t2 = (y - y0) * (x1y1 - x1y0) / (y1 - y0) + x1y0;
}
if (x1 == x0)
return t1;
return (x - x0) * (t2 - t1) / (x1 - x0) + t1;
}
This code is used to get the bilinear interpolation value. currently the only method I have to adjust the value is to add the difference between the desired value and the returned value to all four cell values.
I am trying to solve for y in the following equation using Java:
For the sake of visibility I divided the numerator and denominator into separate variables. I need to compute for x = -3 through x = 4 moving in increments of 0.5.
for(double x = -3; x <= 4; x += .5)
{
// Now we compute the formula for all values in between -3 and 4 in increments of 0.5
double top = ( 9 * Math.pow(x, 3) ) - ( 27 * Math.pow(x, 2) ) - ( (4 * x) + 12 );
double bottom = ( Math.pow(( 3 * Math.pow(x, 2) + 1 ) , 1/2) + Math.abs( 5 - (Math.pow(x, 4)) ) );
double y = top / bottom;
System.out.print("X = " + x + "\t Y = " + y);
}
The values I get are not as intended.
X = -3.0 Y = -6.311688311688312
X = -2.5 Y = -8.880570409982175
X = -2.0 Y = -15.333333333333334
X = -1.5 Y = -91.41176470588235
X = -1.0 Y = -8.8
X = -0.5 Y = -3.0105263157894737
X = 0.0 Y = -2.0
X = 0.5 Y = -3.305263157894737
X = 1.0 Y = -6.8
X = 1.5 Y = -45.529411764705884
X = 2.0 Y = -4.666666666666667
X = 2.5 Y = -1.429590017825312
X = 3.0 Y = -0.3116883116883117
X = 3.5 Y = 0.19940094137783482
X = 4.0 Y = 0.4603174603174603
Using an online tool I computed for X = 0 and got 2 instead of -2. Is there something wrong with how I did the math?
You made a mistake while implementing the expression.
... - ( (4 * x) + 12 )
Should be
... - (4 * x) + 12
Or in the complete expression:
double top = ( 9 * Math.pow(x, 3) ) - ( 27 * Math.pow(x, 2) ) - (4 * x) + 12;
Also as noted by #JacobG:
1/2 evaluates to 0, since it's an integer-division. This doesn't make any difference if you evaluate the for x = 0 though. This can be corrected using 0.5 instead.
There's a small typo in your equation:
1/2
Is equal to 0 in Java; see: Why is the result of 1/3 == 0?
To fix this, you can just type 0.5, or use 1 / 2D or 1D / 2.
See Paul's answer for another issue with your code.
We are trying to get the cos value between v and u but we are getting results much higher than 1 or lesser than 0
Where :
vx = in.nextInt(); // x speed of your pod
vy = in.nextInt(); // y speed of your pod
int ux = nextCheckPointIdX - x;
int uy = nextCheckPointIdY - y;
Here is the formula :
double cos = (vx*ux + vy*uy) / ( Math.sqrt(Math.pow(vx, 2) + Math.pow(vy, 2)) + Math.sqrt(Math.pow(ux, 2) + Math.pow(uy, 2)) );
Do you find any errors in the previous line ?
The denominator was having the problem.
int num = (vx*ux + vy*uy);
double den = (Math.sqrt(Math.pow(vx, 2) + Math.pow(vy, 2)) * (Math.sqrt(Math.pow(ux, 2) + Math.pow(uy, 2))) );
double cos = num / den;
System.out.println(cos);
System.out.println(Math.acos(cos));
Ok let's say like this,
6x = y;
So, what i want is:
x = 0.1y;
2x = 0.2y;
3x = 0.3y;
4x = 0.4y;
5x = 0.5y;
6x = y;
7x = 1.1y;
And so on.
I know to add two numbers but what i want in my program is:
3.5y + 1.4y = 5.3y // not equal to 4.9
33.3 + 45.3 = 79 // not 78.6
40.5 + 34.5 = 75.4 // not 75
6.5y = (6.5*6)x = 41x // not 39x
ok whoever didn't understand my question i want to try it once again:
1 minutes = 60 second // ever one can understand.
and 90 second = 1 min 30 sec // easy enough
if i denote 1 min 30 sec as 1.30 min // just example for my question.
and i need to add
1.30 + 0.30 it will be 1.60 that means 2 minutes.
so, 1.30 + 0.30 = 2;
now 3.50 + 1.40 = 5.30 // according to equation as simple as that.
and the question is how to make a java program to do the above mathematics as i want????
To simplify the problem (and also avoid rounding errors as float and double aren't exact), let's instead express, say, 14.3 as two separate numbers: x = 14, y = 3.
It seems like your problem is that x is in base 10 while y is in base 6. In order to perform addition, we therefore convert them to the same base, add, then convert back:
// Input: four ints (x1, y1, x2, y2)
int a1 = (x1 * 6) + y1;
int a2 = (x2 * 6) + y2;
int a3 = a1 + a2;
int x3 = a3 / 6;
int y3 = a3 % 6;
// Output: two ints (x3, y3)
If you have to use the decimal representation, this should work for you:
double add(double a, double b) {
int x1 = (int) a;
int y1 = (int)Math.round((a - x1) * 10);
int x2 = (int) b;
int y2 = (int)Math.round((b - x2) * 10);
int a1 = (x1 * 6) + y1;
int a2 = (x2 * 6) + y2;
int a3 = a1 + a2;
int x3 = a3 / 6;
int y3 = a3 % 6;
return x3 + (y3 / 10.0);
}
I have calculated the histograms of two images in Java (Code modified and shortened):
for (int posX = 0; posX < image.getWidth(); posX++)
{
for (int posY = 0; posY < image.getHeight(); posY++)
{
Color c1 = new Color(image.getRGB(posX, posY));
cummulative[0] = cummulative[0] + c1.getRed();
cummulative[1] = cummulative[1] + c1.getGreen();
cummulative[2] = cummulative[2] + c1.getBlue();
numPixels++;
}
}
r1 = cummulative[0] / numPixels;
g1 = cummulative[1] / numPixels;
b1 = cummulative[2] / numPixels;
and then calculated the Euclidean Distance of the histograms:
tempDist = Math.sqrt((r1 - r2) * (r1 - r2) + (g1 - g2) * (g1 - g2) + (b1 - b2) * (b1 - b2));
Now I want to calculate the Chi-Squared Distance distance instead the Euclidean Distance. But I have no idea how to implement that. Please can someone give an introduction for that?
Edit:
I have now the following code to generate the histogram:
float[] histogram = new float[256];
for (int i = 0; i < input.getWidth(); i++) {
for (int j = 0; j < input.getHeight(); j++) {
int color = 0;
switch (colorVal) {
case 1:
color = new Color(input.getRGB(i, j)).getRed();
break;
case 2:
color = new Color(input.getRGB(i, j)).getGreen();
break;
case 3:
color = new Color(input.getRGB(i, j)).getBlue();
break;
}
histogram[color]++;
}
}
How can I continue supposed I have the following Data:
Image 1:
R 10 count 1000
R 20 count 100
R 30 count 100
G 20 count 600
G 255 count 600
B 0 count 800
B 200 count 400
Image 2:
R 10 count 1000
R 20 count 200
G 20 count 600
G 255 count 600
B 0 count 800
B 100 count 200
B 200 count 200
you have just summed up the r,g,b values, and not computed a histogram. First, compute the histogram correctly, then Chi squared distance can be computed as d(x,y) = sum( (xi-yi)^2 / (xi+yi) ) / 2, where x and y are your histograms, and i is the bin index of the histogram