有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

一组点之间的java快速插值

我用爪哇建立了一个太阳系模型。为了确定一颗行星的位置,它需要做大量的计算,给出一个非常精确的值。然而,我经常对大致的位置感到满意,如果这能让它走得更快的话。因为我在模拟中使用它,速度很重要,因为行星的位置将被请求数百万次

目前,我试图缓存行星在其整个轨道上的位置,然后反复使用这些坐标。如果请求两个值之间的位置,我将执行线性插值。这就是我存储价值的方式:

for(int t=0; t<tp; t++) {
    listCoordinates[t]=super.coordinates(ti+t);
}

interpolator = new PlanetOrbit(listCoordinates,tp);

PlanetOrbit有插值代码:

package cometsim;

import org.apache.commons.math3.util.FastMath;

public class PlanetOrbit {

    final double[][] coordinates;
    double tp;

    public PlanetOrbit(double[][] coordinates, double tp) {
        this.coordinates = coordinates;
        this.tp = tp;
    }

    public double[] coordinates(double julian) {
        double T = julian % FastMath.floor(tp);

        if(coordinates.length == 1 || coordinates.length == 0) return coordinates[0];

        if(FastMath.round(T) == T) return coordinates[(int) T];

        int floor = (int) FastMath.floor(T);

        if(floor>=coordinates.length) floor=coordinates.length-5;

        double[] f = coordinates[floor];
        double[] c = coordinates[floor+1];

        double[] retval = f;
        retval[0] += (T-FastMath.floor(T))*(c[0]-f[0]);
        retval[1] += (T-FastMath.floor(T))*(c[1]-f[1]);
        retval[2] += (T-FastMath.floor(T))*(c[2]-f[2]);

        return retval;
    }
}

你可以把FastMath想象成Math,但速度更快。然而,与每次计算精确值相比,这段代码并没有多大的速度提升。你有什么办法让它更快吗


共 (1) 个答案

  1. # 1 楼答案

    有几个问题我可以看到,我可以看到的主要问题如下

    • PlanetOrbit#coordinates似乎实际上改变了变量coordinates中的值。由于这种方法应该只进行插值,所以我预计每次运行轨道时,轨道实际上都会略微损坏(因为这是一种线性插值,轨道实际上会朝中心退化)
    • 同样的事情做了几次,最明显的是T-FastMath.floor(T)在代码中分别出现了3次
    • 这不是效率或准确性的问题,但变量和方法名称非常不透明,请使用实词作为变量名称

    我提议的方法如下

    public double[] getInterpolatedCoordinates(double julian){ //julian calendar? This variable name needs to be something else, like day, or time, or whatever it actually means
        int startIndex=(int)julian;
        int endIndex=(startIndex+1>=coordinates.length?1:startIndex+1); //wrap around
    
        double nonIntegerPortion=julian-startIndex;
    
    
        double[] start = coordinates[startIndex];
        double[] end = coordinates[endIndex];
    
        double[] returnPosition= new double[3];
    
        for(int i=0;i< start.length;i++){
            returnPosition[i]=start[i]*(1-nonIntegerPortion)+end[i]*nonIntegerPortion;
        }
        return returnPosition;
    }
    

    这可以避免损坏坐标数组,并避免重复同一楼层几次(1-nonIntegerPortion仍会重复几次,如果需要,可以删除,但我希望分析将显示它没有什么意义)。但是,它每次都会创建一个新的double[],如果您只需要临时使用该数组,那么这可能会降低效率。这可以通过使用store对象(以前使用但不再需要的对象,通常来自上一个循环)来纠正

    public double[] getInterpolatedCoordinates(double julian, double[] store){
        int startIndex=(int)julian;
        int endIndex=(startIndex+1>=coordinates.length?1:startIndex+1); //wrap around
    
        double nonIntegerPortion=julian-startIndex;
    
    
        double[] start = coordinates[startIndex];
        double[] end = coordinates[endIndex];
    
        double[] returnPosition= store;
    
        for(int i=0;i< start.length;i++){
            returnPosition[i]=start[i]*(1-nonIntegerPortion)+end[i]*nonIntegerPortion;
        }
        return returnPosition; //store is returned
    }