关于java:如何计算大数字的行进距离?

How could we calculate traveled distance, with big numbers?

我目前正在解决此kata:"我要走多远?"!

说明说:

You have recently discovered that horses travel in a unique pattern -
they're either running (at top speed) or resting (standing still).

Here's an example of how one particular horse might travel:

The horse Blaze can run at 14 metres/second for 60 seconds, but must
then rest for 45 seconds.

After 500 seconds Blaze will have traveled 4200 metres.

Your job is to write a function that returns how long a horse will
have traveled after a given time.

输入:

1
2
3
4
5
6
7
totalTime - How long the horse will be traveling (in seconds)

runTime - How long the horse can run for before having to rest (in seconds)

restTime - How long the horse have to rest for after running (in seconds)

speed - The max speed of the horse (in metres/second)

我已经手工完成了演算:

给出:速度= 14,运行时间= 60,rest时间= 45,总时间= 500

->要计算马跑多少时间,我们计算以下内容:

totalTime /(runTime restTime)= 500 /(60 45)= 500/105 = 4.76 ...
roundUp(totalTime)= 5

总运行时间= 5 *运行时间= 5 * 60 = 300

->要计算马走过的距离:

x =速度* totalRunTime = 14 * 300 = 4200

我将其翻译为以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class Kata {

    public static int travel(int totalTime, int runTime, int restTime, int speed) {
      int totalRunTime = 0;

      if(totalTime < runTime){
        totalRunTime = totalTime;
      }else{
        totalRunTime = (int)Math.ceil( (double)totalTime/(runTime + restTime) ) * runTime;
      }

      return speed * totalRunTime;
    }
}

运行基本测试时,它会提供预期的输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import org.junit.runners.JUnit4;


public class KataTest {

    @Test
    public void exampleTests() {
        assertEquals(4200, Kata.travel(500, 60, 45, 14));
        assertEquals(1120, Kata.travel(1000, 10, 127, 14));
        assertEquals(1000, Kata.travel(100, 10, 0, 10));
        assertEquals(1000, Kata.travel(100, 10, 0, 10));
        assertEquals(450, Kata.travel(25, 50, 120, 18));
    }
}

但是,当我们使用数字更大的高级示例进行测试时,它显示的结果不准确。

例如:

给出:速度= 6,运行时间= 34,rest时间= 180,总时间= 99094;预期的输出为94524,但是我发布的代码为我们提供了94656

我手动编写了跟踪以了解我的代码的作用:

->要计算这匹马奔跑的总时间:

totalTime /(runTime restTime)= 99094 /(34180)= 99094/214 = 463.05 ...
roundUp(totalTime)= 464

总运行时间= 464 *运行时间= 464 * 34 = 15776

->要计算马走了多远:

x =速度* totalRunTime = 6 * 15776 = 94656

因此失败的测试是:

1
2
3
4
5
6
7
8
9
10
11
12
import org.junit.Test;
import static org.junit.Assert.assertEquals;
import org.junit.runners.JUnit4;


public class KataTest {

    @Test
    public void biggerTests() {
        assertEquals(84954920, Kata.travel(35869784, 90, 100, 5));
    }
}

我的直觉是必须在从double到int的转换或使用Math.ceil进行四舍五入的过程中改进代码,但是我不知道为什么或如何解决它。这是我认为我们可以改进的内容:

1
totalRunTime = (int)Math.ceil( (double)totalTime/(runTime + restTime) ) * runTime;

我也读过:

  • 计算行驶距离
  • AnyLogic:如何计算行人的行进距离?
  • 计算行进距离(而不是两者之间的距离)
  • 如何计算旅行的总距离?
  • https://www.tutorialspoint.com/java/lang/math_ceil.htm


问题不在于四舍五入。
让我们看一下示例travel(35869784, 90, 100, 5)

根据您的公式35869784/(100+90) = 188788.336,向上舍入得出188789,乘以runTime,然后乘以speed得到84,955,050米,而正确的答案是84,954,920。这不是一个四舍五入的问题。公式错误。

为什么?考虑最后一次rest后的跑步。这匹马已经进行了90,100s的188,788次完整迭代,在此过程中,它在35,869,720秒内覆盖了84,954,600米的距离。在这些"满员"奔跑之后,这匹马现在只剩下64秒可以跑了,这比runTime

还要短。

这匹马在64秒内跑了多远? 320米。因此总数为84,954,600 + 320 = 84,954,920米。