我正在写一个非常标准的双三次插值程序。由于某种原因,如果我将Xincrement和Yincrement设置得太小,For循环就会过早地退出一次。不知道为什么会这样。我在main中设置了Yincrement和Xincrement,如果它们是0.25或更高,那么它工作得很好,但如果我将其减少到0.2或更低,它会提前停止一个循环。另外,最后3个for循环也会出错。
下面是我的代码:
public static double ApplyKernel(double [] Row, double Location, int R) {
double s1; double s2; double s3; double s4;
double Kernel;
double s = Location%1;
s1 = -.5*Math.pow(s+1,3)+2.5*Math.pow(s+1,2)-4*(s+1)+2;
s2 = 1.5*Math.pow(s,3)-2.5*Math.pow(s,2)+1;
s3 = 1.5*Math.pow(1-s,3)-2.5*Math.pow(1-s,2)+1;
s4 = -.5*Math.pow(2-s,3)+2.5*Math.pow(2-s,2)-4*(2-s)+2;
if(s==0) {
Kernel = Row[(int)(Location)];
} else {
Kernel = s1*Row[(int)(Location-1)]+s2*Row[(int)Location]+s3*Row[(int) (Location+1)]+s4*Row[(int)(Location+2)];
}
return Kernel;
}
public static double[][] zValues(double [][] ExtendP, int R, double X, double Y, double Xincrement, double Yincrement) throws FileNotFoundException
{
String phFileName = "Data37.txt";
PrintStream phOutput = new PrintStream( phFileName );
double[][] zValues = new double[(int)(R/Xincrement)+1][(int)(R/Yincrement)+1];
double[] row = new double[R+3];
for (double i = 1; i<=(R+1); i += Xincrement) {
phOutput.println(";");
for (int j = 0; j<R+3; j++) {
row[j] = ApplyKernel(ExtendP[j], i, R);
}
for(double k = 1; k<=(R+1); k += Yincrement) {
zValues[(int)((i-1)/Xincrement)][(int)((k-1)/Yincrement)] = ApplyKernel(row, k, R);
phOutput.printf("(%.2f,%.2f) = %.3f ", k, i, ApplyKernel(row, k, R));
}
}
return zValues;
}
如果你们知道为什么会这样,请告诉我
主要建议:不要迭代double
。通过反复添加,您正在积累错误,在某些情况下,您将遭受栅栏问题。
相反,迭代int
并使用适当的公式在单个计算步骤中推导出双精度值。这只需要对整数进行适当的缩放。
当你像这样循环代码时,你真的应该使用ints
来进行循环。整型是精确的,不会被近似。
使用double进行循环将导致舍入误差或不精确,这是由于表示double的近似性质。当您不断修改变量时,这个错误会变得更大。
看起来像一个浮点错误。由于R
为int
类型,而i,k为double类型,因此可能存在理论上相等的比较,但由于浮点精度的原因,可能不会计算为相等。