下面的代码正确地找到了数组的局部最大值,但是找不到局部最小值。我已经完成了网络搜索以找到找到最小值的最佳方法,我认为我正在使用下面的正确方法,基于这些搜索。但是在下面的代码中有一些错误,我仍然没有看到,在几天的过程中多次遍历每一行。
变量startX和endX定义用户选择的窗口,代码必须在该窗口中找到本地最小值/最大值。如果你操作startX和endX的值,你会看到下面的代码总是输出最小值作为所选窗口的第一个索引,这表明它没有迭代窗口中的索引来搜索最小值。 / p>
任何人都可以找到该错误并告诉我如何修复下面的代码以找到本地最小值?
class LocalMinMax {
static double[] pts;
static int visiblePoints=5000;
static int startX = 200;
static int endX = 700;
public static void main (String[] args) {
int lastX2 = 0;
int maxWidth = 800;
double hstep = (double) maxWidth / visiblePoints;
int maxHeight = 400;
pts = new double[visiblePoints];
double max = Double.NEGATIVE_INFINITY;
double min = Double.POSITIVE_INFINITY;
int minIndex = -1;
int maxIndex = -1;
for (int i = 0; i < visiblePoints; i++){
pts[i] = (double) ((((Math.sin(.009*i))*(Math.cos(.004*i))) * (maxHeight/3) * .95) + (maxHeight/2));
int x2 = (int) (i * hstep);
if(x2>=startX){
int sectionStartIndex = i;
int sectionEndIndex = (int)(endX/hstep);
for(int k=sectionStartIndex;k<sectionEndIndex;k++){
if(min>pts[k]){
min = pts[k];
minIndex = x2;
System.out.println("minIndex, min, pts["+k+"]: , x2 are: "+minIndex+", "+min+", "+pts[k]+", "+x2);
}
if(max<pts[k]){
max = pts[k];
maxIndex = x2;
}}}
if(lastX2!=x2){
lastX2=x2;
if(x2==startX){
int width = endX - startX;
System.out.println("WINDOW: width, startX, endX are: "+width+", "+startX+", "+endX);
}}}
int maxVal = (int)max;
int minVal = (int)min;
System.out.println("LOCAL MAX: maxIndex, maxVal are: "+maxIndex+", "+maxVal);
System.out.println("LOCAL MIN: minIndex, minVal are: "+minIndex+", "+minVal);
}}
答案 0 :(得分:2)
一种方法是通过sectionStartIndex..sectionEndIndex
窗口扫描向后,如下所示。这不是解决方案,但它会让你看到绿色矩形在跟踪最小值时上下移动。
for (int k = sectionStartIndex; k < sectionEndIndex; k++) {
int j = sectionEndIndex - k;
if (min > pts[j]) {
System.out.println("minIndex, min, pts[" + j + "]: "
+ minIndex + ", " + min + ", " + pts[j]);
min = pts[j];
minIndex = x2Count;
}
if (max < pts[k]) {
max = pts[k];
maxIndex = x2Count;
}
}
附录:将数组初始化提升到循环之外是一种方法,如下所示。请注意在缩放操作中使用double
除数。
更严重的问题是在一个域中评估函数,而在另一个域中对其进行采样。我将视图(鼠标坐标)与模型分开(double
表示的实数)。介绍在两者之间转换坐标的方法,例如*scale*
函数here。让模型在鼠标移动时评估函数;只有在证明有必要时才进行优化。
Local: maxIndex, maxVal: 200, 326 Local: minIndex, minVal: 200, 79
class LocalMinMax {
static double[] pts;
static int visiblePoints = 5000;
static int startX = 200;
static int endX = 700;
public static void main(String[] args) {
int lastX2 = 0;
int maxWidth = 800;
double hstep = maxWidth / (double) visiblePoints;
int maxHeight = 400;
pts = new double[visiblePoints];
for (int i = 0; i < pts.length; i++) {
pts[i] = (((Math.sin(.009 * i)) * (Math.cos(.004 * i)))
* (maxHeight / 3d) * .95) + (maxHeight / 2d);
}
double max = Double.NEGATIVE_INFINITY;
double min = Double.POSITIVE_INFINITY;
int minIndex = -1;
int maxIndex = -1;
for (int i = 0; i < visiblePoints; i++) {
int x2 = (int) (i * hstep);
if (x2 >= startX) {
int sectionStartIndex = i;
int sectionEndIndex = (int) (endX / hstep);
for (int k = sectionStartIndex; k < sectionEndIndex; k++) {
if (min > pts[k]) {
min = pts[k];
minIndex = x2;
//System.out.println("minIndex, min, pts[" + k + "], x2: "
//+ minIndex + ", " + min + ", " + pts[k] + ", " + x2);
}
if (max < pts[k]) {
max = pts[k];
maxIndex = x2;
//System.out.println("maxIndex, max, pts[" + k + "], x2: "
//+ maxIndex + ", " + max + ", " + pts[k] + ", " + x2);
}
}
}
if (lastX2 != x2) {
lastX2 = x2;
if (x2 == startX) {
int width = endX - startX;
}
}
}
int maxVal = (int) max;
int minVal = (int) min;
System.out.println("Local: maxIndex, maxVal: " + maxIndex + ", " + maxVal);
System.out.println("Local: minIndex, minVal: " + minIndex + ", " + minVal);
}
}
答案 1 :(得分:2)
由于函数f(x) = sin(ax) + cos(bx)
是(至少)两次differentiable,另一种方法是分析地找到最小值和最大值。只要一阶导数为零,函数就会有一个局部extremum。二阶导数的符号表示极值是最小值还是最大值。