比较for循环中两个有符号整数的奇怪行为

时间:2016-11-05 18:59:30

标签: java for-loop conditional boolean-expression signed-integer

我正在尝试解决如下所述的问题:给定一个设定的段和一组点,计算每个点包含多少个段。

我遇到的问题是当我必须计算一个段包含一个点的次数。当我有一个特定的输入时,内部循环正确地递增每个点的计数器,当我有另一个数据集时会出现天气,其中将零与负数进行比较并且发生非负数,它表现得很奇怪。

以下只是为了找到我所面临的问题而创建的脚本,并不代表实际的实现。

测试用例给出如下输出:

案例1:

    String debug = "Test case 1: \n ";
    debug += " \n - 2 Segments with coordinates [0, 5] and [7, 10].";
    debug += " \n - 3 points at the coordinates 1, 6, and 11.";
    int [] starts = new int[]{0, 7};
    int [] ends = new int[]{5, 10};
    int [] points = new int[]{1, 6, 11};

    debug += "\n \n Calculating the coverage of the points: ";
    for ( int i=0; i<starts.length; i++) {
        for (int j=0; j<points.length && ( starts[i] <= points[j] && points[j] <= ends[i]); j++) {
            debug += " \n * Point with coordinate " + points[j] + ", is between " + starts[i] + " and " + ends[i];
        }
    }
    debug += "\n \n FINISHED the calculation!";

    int start = 0, point = 1, end = 5;
    debug += "\n \n Custom check for the 1st point: ";
    debug += "\n - Is (" + start + " <= " + point + " and " + point + " <= " + end + ")? " + ( start <= point && point <= end );
    System.out.println(debug);

输出:

测试案例1:

  • 2坐标为[0,5]和[7,10]的段。
  • 在坐标1,6和11处有3个点。

    计算积分的覆盖范围:

  • 坐标为1的点,介于0和5之间

    完成计算!

    第一点的自定义检查:

  • 是(0 <= 1且1 <= 5)?真

案例2:

    String debug = "Test case 2: \n ";
    debug += " \n - 1 Segment with coordinates [-10, 10].";
    debug += " \n - 3 points at the coordinates -100, 100, and 10.";
    int [] starts = new int[]{-10};
    int [] ends = new int[]{10};
    int [] points = new int[]{-100, 100, 0};

    debug += "\n \n Calculating the coverage of the points: ";
    for ( int i=0; i<starts.length; i++) {
        for (int j=0; j<points.length && ( starts[i] <= points[j] && points[j] <= ends[i]); j++) {
            debug += " \n * Point with coordinate " + points[j] + ", is between " + starts[i] + " and " + ends[i];
        }
    }
    debug += "\n \n FINISHED the calculation!";

    int start = -10, point = 0, end = 10;
    debug += "\n \n Custom check: ";
    debug += "\n - Is (" + start + " <= " + point + " and " + point + " <= " + end + ")? " + ( start <= point && point <= end );
    System.out.println(debug);

输出:

测试案例2:

  • 1坐标为[-10,10]的段。
  • 坐标-100,100和10处有3个点。

    计算点数的覆盖范围:

    完成计算!

    自定义检查:

  • 是(-10 <= 0和0 <= 10)?真

正如你所看到的,内环的条件在某种程度上不能相对于段[-10,10]适当地计算坐标为0的点的情况。

提前致谢, Endrit。

2 个答案:

答案 0 :(得分:0)

您的问题在于for循环条件:

for (int j=0; j<points.length && ( starts[i] <= points[j] && points[j] <= ends[i]); j++) {

只要您遇到point[j]starts[i]之间的任何ends[i],那么循环将终止,您不会检查任何后续点。

相反,您应该将循环条件与交叉条件分开。在伪代码中:

for every (start, end) pair:
    for every point:
         if point intersects (start, end):
              increment counter
         otherwise continue to next point

这有意义吗?

答案 1 :(得分:0)

要从points.Length * ends.Length减少大O订单,您可以同时循环两者。我假设片段不能重叠。

Array.sort(starts);
Array.sort(ends);
Array.sort(points);
int pointIndex = 0;
String debug = ""
int numCollisions = 0;
bool collides = False;
for (int i=0; i < ends.length; i++) {
    debug += "Points between " + starts[i] + " and " + ends[i] ":\n";
    while (pointIndex < points.Length && points[pointIndex] < starts[i]) {
        pointIndex++;
    }
    while (pointIndex < points.Length && points[pointIndex] <= ends[i]) {
        numCollisions++;
        debug += "    " + points[pointIndex] "\n";
        pointIndex++;
    }
}
debug += "Total number of collisions: " + numCollisions;
System.out.println(debug);

//原始回复:

在测试用例2中,您在内循环(i==0j==1)的第二次迭代时退出for循环,因为points[j] == 100ends[i] == 10。由于您已退出循环,因此永远不会检查0。

在进入for循环之前尝试排序points