Percy

根据差异,将数组过滤为每十个倍数的一行?

java

我有一个数组,用于保存结果集中的值。我检索数组的代码的概要是:

public String[][] ref_Details() {
  int i = 0;
  String a[][] = new String[47][11];
  try
  {  
    con = getConnection();
    stmt = con.createStatement();
    String sql=" select b.LOGTIME, b.beam_current, b.beam_energy ..."; // shortened
    stmt.executeQuery(sql);
    rs = stmt.getResultSet();

    while(rs.next()) {
      for(int j=0; j<11; j++)
        a[i][j] = rs.getString(j+1);

      i++;
    }
  }
  catch( Exception e ) { ... }
  finally {
    closeConnection(stmt, rs, con);
  }
  return a;
}

获得的样本表是:

在此处输入图片说明

从表中可以明显看出,第二列的beam_current值接近0到220:(0,10,20 … 220)的每个十的整数倍。我想过滤我的数据集,以便对于10的倍数,只选择最接近该倍数的行。为此,我:

从的所有行中减去10,beam_current然后找到获得的差值:差最小的行是我感兴趣的唯一行,即10的倍数。T
重复步骤1,直到从所有行中总共减去220。
我的预期结果是22行,而不是样本数据中的原始47行。例如,上面样本数据图片中编号为21的行将对应于该值的选定行130。

我的问题是我没有看到预期的结果。我试过的代码是:

public int[] ref_BeamCurrent() {
  int i = 0;
  int[] arr = new int[47];
  try
  {  
    con = getConnection();
    ...
    rs = stmt.getResultSet();

    while(rs.next()) 
    { 
      for(i=0; i<arr.length; i++)
      {
        arr[i] = rs.getInt(2);
        System.out.println(arr);
        while (i < arr.length && number <= 210)
        {
          arr[i] = arr[i] - number;
          System.out.println(arr);
          number = number + 10;
          System.out.println(number);
          i = i + 1;
          // System.out.println(arr);
        }
      }
    }
  }
  catch( Exception e ) { ... }
  finally { ... }
  return arr;
}

这段代码似乎在选择完全错误的行-我在做什么错?


阅读 268

收藏
2020-12-05

共1个答案

一尘不染

我认为您应该以不同的方式来考虑。您想要做的是找到每行十的倍数的距离。

十进制的最接近倍数由表达式给出 double mult = 10d * Math.round(v / 10d)
与十的倍数的距离由表达式给出 double delta = Math.abs(v - mult)
对于的任何值mult,您要的行都是最小的行delta。
因此,您只需要迭代行一次。

  1. beam_value连续获取并找到multdelta
  2. 如果行的delta比以前发现的任何接近deltamult,然后再登录该行为mult,否则忽略它。
  3. 重复直到没有更多行。
    还要注意,这种方法将防止记录一行超过十的整数倍,而其他方法很难防止这种情况。

通过示例(由于我没有您的SQL查询,所以我伪造了数据)。输入数据:

`0.5, 12.10, 13.00, 16.01, 21.52`

给出下面的输出,它是正确的(索引110比索引2更近,索引420比索引3更近):

   10x  row value
     0 0 0.5000
    10 1 12.1000
    20 4 21.5200

与代码:

public static void findClosestRowsToMultiplesOfTen() {
    // fake row values
    double[] vals = new double[]{ 0.5, 12.10, 13.00, 16.01, 21.52 };

    //  get the max value, and its multiple of ten to get the number of buckets
    double max = Double.MIN_VALUE;
    for (double v : vals) max = Math.max(max, v);
    int bucketCount = 1 + (int)(max/10);

    //  initialise the buckets array to store the closest values
    double[][] buckets = new double[bucketCount][3];
    for (int i = 0; i < bucketCount; i++){
        // store the current smallest delta in the first element
        buckets[i][0] = Double.MAX_VALUE; 
        // store the current "closest" index in the second element
        buckets[i][1] = -1d;
        // store the current "closest" value in the third element
        buckets[i][2] = Double.MAX_VALUE;
    }

    //  iterate the rows
    for (int i = 0; i < vals.length; i++)
    {
        //  get the value from the row
        double v = vals[i];
        //  get the closest multiple of ten to v
        double mult = getMultipleOfTen(v);
        //  get the absolute distance of v from the multiple of ten
        double delta = Math.abs(mult - v);
        //  get the bucket index based on the value of `mult`
        int bIdx = (int)(mult / 10d);
        //    test the last known "smallest delta" for this bucket
        if (buckets[bIdx][0] > delta)
        {
            //  this is closer than the last known "smallest delta"
            buckets[bIdx][0] = delta;
            buckets[bIdx][1] = i;
            buckets[bIdx][2] = v;
        }
    }

    //   print out the result
    System.out.format("    10x row value%n");
    for (int i = 0; i < buckets.length; i++)
    {
        double[] bucket = buckets[i];
        int multipleOfTen = i * 10;
        double rowIndex = bucket[1];
        double rowValue = bucket[2];
        System.out.format("    %,2d %,4.0f %.4f%n", 
          multipleOfTen, rowIndex, rowValue);
    }
}
public static double getMultipleOfTen(double v)
{
    return 10d * Math.round(v / 10d);
}
2020-12-05