Java 阵列(或两个)上的插值
我正在寻找一个java库或一些帮助来编写我自己的插值函数。也就是说,我有两个double数组,它们可能大小不同,但是是有序的。我需要能够估计中间值,并进行插入,以便两个数组的大小相同。事实上,插值中出现的总点数是两个数组大小之和减去1。但是,每个阵列的范围必须保持不变,因此不需要外推 a1=[1,4,9,16,25,36]和a2=[6,9,14,30] 结果可能是 a1=[1,2.25,4,6.25,9,12.25,16,25,36] 和 a2=[6,6.5625,7.25,9,10.0625,11.25,14,25.25,30]Java 阵列(或两个)上的插值,java,dataset,interpolation,Java,Dataset,Interpolation,我正在寻找一个java库或一些帮助来编写我自己的插值函数。也就是说,我有两个double数组,它们可能大小不同,但是是有序的。我需要能够估计中间值,并进行插入,以便两个数组的大小相同。事实上,插值中出现的总点数是两个数组大小之和减去1。但是,每个阵列的范围必须保持不变,因此不需要外推 a1=[1,4,9,16,25,36]和a2=[6,9,14,30] 结果可能是 a1=[1,2.25,4,6.25,9,12.25,16,25,36] 和 a2=[6,6.5625,7.25,9,10.0625,
这些例子是
f(x)=x^2和g(x)=x^2+5
,但是很可能是任何多项式-关键是能够从数据集很好地估计/近似函数,以提供足够好的插值。这里的x值只是输入数组的索引。在输出中,只有y值是重要的。简单的线性插值可以使用以下方法计算:
Point2D interp1_lin(Point2D p1, Point2D p2, double x) {
//Pre conditions
assert p1.x<x;
assert x<p2.x;
//Calculate slope from p1 to p2
double m = (p2.x-p1.x)/(p2.y-p1.y);
//Calculate y position of x
double y = (x-p1.x)*m+p1.y;
//create new point
return new Point2D.Double(x,y);
}
Point2D接口(Point2D p1、Point2D p2、双x){
//先决条件
断言p1.x您需要获得对应于y值的x值。否则,没有算法能够确定[1,16,81]是[1,4,9]的x^2还是[1,2,3]的x^4。您是插值六个值还是不插值
然后,当你得到x值时,你可以使用某种插值(线性,kubic样条,你可以说)来近似缺少的值。其他答案给你线性插值——这些插值对复杂的非线性数据并不有效。我想你需要一种,(样条插值)。
样条拟合使用数据中的一组控制点来描述数据区域,然后在控制点之间应用多项式插值。控制点越多,拟合越精确。样条拟合比线性拟合精确得多,使用速度比一般回归拟合快,比高阶拟合好因为它不会在控制点之间做疯狂的事情
我一时记不起名字,但Java中有一些非常适合的库——我建议您寻找一个,而不是编写自己的函数
**编辑:可能有用的库:**
- (希望你能读德语)
**可能有用的理论/代码:**
- 带代码的样条线小程序:
- 多边形线到bezier样条曲线的样条曲线拟合
- 样条曲线,以及一些拟合的数学。如果库不这样做,更多的数学,更少的代码可能会有所帮助
专为一维数据阵列设计
import java.util.ArrayList;
public class Interpolator {
public static Float CosineInterpolate(Float y1,Float y2,Float mu)
{
double mu2;
mu2 = (1.0f-Math.cos(mu*Math.PI))/2.0f;
Float f_mu2 = new Float(mu2);
return(y1*(1.0f-f_mu2)+y2*f_mu2);
}
public static Float LinearInterpolate(Float y1,Float y2,Float mu)
{
return(y1*(1-mu)+y2*mu);
}
public static Float[] Interpolate(Float[] a, String mode) {
// Check that have at least the very first and very last values non-null
if (!(a[0] != null && a[a.length-1] != null)) return null;
ArrayList<Integer> non_null_idx = new ArrayList<Integer>();
ArrayList<Integer> steps = new ArrayList<Integer>();
int step_cnt = 0;
for (int i=0; i<a.length; i++)
{
if (a[i] != null)
{
non_null_idx.add(i);
if (step_cnt != 0) {
steps.add(step_cnt);
System.err.println("aDDed step >> " + step_cnt);
}
step_cnt = 0;
}
else
{
step_cnt++;
}
}
Float f_start = null;
Float f_end = null;
Float f_step = null;
Float f_mu = null;
int i = 0;
while (i < a.length - 1) // Don't do anything for the very last element (which should never be null)
{
if (a[i] != null && non_null_idx.size() > 1 && steps.size() > 0)
{
f_start = a[non_null_idx.get(0)];
f_end = a[non_null_idx.get(1)];
f_step = new Float(1.0) / new Float(steps.get(0) + 1);
f_mu = f_step;
non_null_idx.remove(0);
steps.remove(0);
}
else if (a[i] == null)
{
if (mode.equalsIgnoreCase("cosine"))
a[i] = CosineInterpolate(f_start, f_end, f_mu);
else
a[i] = LinearInterpolate(f_start, f_end, f_mu);
f_mu += f_step;
}
i++;
}
return a;
}
}
我知道这是一个古老的答案,但这是谷歌搜索Java插值时的第一个成功答案。公认的答案提供了一些有用的链接,但必须购买JMSL,而且JSpline+网站看起来很粗略
ApacheCommonsMath提供了线性插值和样条插值的实现,这些实现看起来简单、功能强大且值得信赖
重量轻的一维阵列线性插值器:
public static float[] interpolate(float[] data) {
int startIdx = -1;
float startValue = 0f;
float element;
for (int i = 0; i < data.length - 1; i++) {
element = data[i];
if (element != 0f) {
if (startIdx != -1) {
doInterpolate(startValue, element, startIdx + 1, i - startIdx - 1, data);
}
startValue = element;
startIdx = i;
}
}
return data;
}
private static void doInterpolate(float start, float end, int startIdx, int count, float[] data) {
float delta = (end - start) / (count + 1);
for (int i = startIdx; i < startIdx + count; i++) {
data[i] = start + delta * (i - startIdx + 1);
}
}
公共静态浮点[]插值(浮点[]数据){
int startIdx=-1;
浮动起始值=0f;
浮动元件;
对于(int i=0;i
使用样条拟合和多项式拟合时要非常小心。这两种拟合可能会产生荒谬的行为,可能会破坏数据的许多用途(据信是数据的表示)
任何使用数据导数(斜率)的东西都可能完全出轨
您可以做的最好的事情是绘制数据,了解它在做什么,然后拟合(线性、多项式、对数)回归;一旦这样做,您应该绘制原始数据的拟合图,并确保您看到合理的一致性。跳过此比较步骤是一个非常糟糕的主意
某些数据集不会屈服于多项式、对数等的拟合;如果数据点在数据范围内适当分布,则分段插值(线性或多项式等)没有问题。要想打败一匹死马,如果你使用分段插值,请避免使用分段插值的导数/斜率,因为它会有不连续性,并会导致事情表现不好。你可以使用插值,例如你的问题有点不清楚。你能给我们一个简单的具体例子吗?我已经编辑过举个例子,虽然它不一定是一个函数可以给出的输出,但我认为它展示了一个可接受的输出。好的,我没有正确地思考我的例子-假设每个数组索引都是输入的x值-然后在插值之后,我们对x值不再感兴趣。是的,这正是我想要的之后…更具体地说,这些库是什么和在哪里。我添加了一些库的链接,如果库没有,则使用code+theory来处理样条线。如果对您有帮助,请不要忘记接受答案!还有专门用于此目的的LinerarInterpolator。返回空值。
public static float[] interpolate(float[] data) {
int startIdx = -1;
float startValue = 0f;
float element;
for (int i = 0; i < data.length - 1; i++) {
element = data[i];
if (element != 0f) {
if (startIdx != -1) {
doInterpolate(startValue, element, startIdx + 1, i - startIdx - 1, data);
}
startValue = element;
startIdx = i;
}
}
return data;
}
private static void doInterpolate(float start, float end, int startIdx, int count, float[] data) {
float delta = (end - start) / (count + 1);
for (int i = startIdx; i < startIdx + count; i++) {
data[i] = start + delta * (i - startIdx + 1);
}
}