# [Java] Generating a Time Array Problem

1. Nov 8, 2012

### testme

1. The problem statement, all variables and given/known data
I'm given a maximum time, a time step (or interval) and I'm supposed to form an array from 0 to the maximum time going up by timestep each time.

double tMax; //maximum time
double tStep; //time interval to go up by

2. Relevant equations
Our teacher told us to use the following equation:
ti = ti-1 + tStep

3. The attempt at a solution

public static double[] timeArray(double tMax, double tStep)
{
double[] timeArr = new double[(int)(tMax/tStep) + 1];
timeArr[0] = [0];
for(int i = 1; timeArr[i - 1] <= tMax; i++)
{
timeArr = timeArr[i - 1] + tStep;
}
return timeArr;
}

public static void displayTime(double[] timeArr)
{
int n = timeArr.length;
System.out.println("Time");
for(int i = 0; i < n; i++)
{
System.out.println(timeArr);
}
}

Everything seems to be working however when I print out the time array (using 1 as tMax and 0.05 as tStep) it gives me the list of values such as:

0.0
0.05
0.1
0.15000000000000002
0.2
0.25
0.3
0.35
0.39999999999999997
0.44999999999999996
0.49999999999999994
0.5499999999999999
0.6
0.65
0.7000000000000001
0.7500000000000001
0.8000000000000002
0.8500000000000002
0.9000000000000002
0.9500000000000003
1.0000000000000002

Can anyone tell me why it's adding or taking off .000000000000000#? and how to fix it

2. Nov 8, 2012

### Ibix

Can you write 0.05 in binary?

String.format will help with your problem.

On the subject of rounding errors, what will the array size be if tmax/tstep is 11.99999999? What will happen with the populating loop if you use tmax=0.5 and tstep=0.05?

Last edited: Nov 9, 2012
3. Nov 9, 2012

### testme

Umm, do you mean when the user enters it or in general?

if I remember right
1111

Also, I don't think we're allowed to use string format.

I believe we're supposed to assume that tMax = ntStep, where n can be any integer. So tMax/tStep can't be 11.999999999 or anything of the sort.

using tmax = 0.5, tstep = 0.05

(tmax/tstep) + 1 = 11
timeArr = new double[11];

timeArr[0] = 0;
timeArr[1] = 0.05;
timeArr[2] = 0.1;
timeArr[3] = 0.15;
timeArr[4] = 0.2;
timeArr[5] = 0.25;
timeArr[6] = 0.3;
timeArr[7] = 0.35;
timeArr[8] = 0.4;
timeArr[9] = 0.45;
timeArr[10] = 0.5;

4. Nov 9, 2012

### Staff: Mentor

No. 1111 is the binary representation of 1510. The binary representation of .05 is an infinitely long binary fraction. Since computers can't hold infinitely long numbers, they truncate them to fit, which causes truncation errors. This is why you are getting the results you show.

5. Nov 9, 2012

### rcgldr

To reduce rounding error related to repeated additions, try changing

Code (Text):

timeArr[i] = timeArr[i - 1] + tStep;

to

Code (Text):

timeArr[i] = i * tStep;

It's also possible to reduce rounding errors due to repeated additions by using a function and an array of 2048 doubles to hold intermediate sums where the index into the array is based on the exponent of 2 of a double precision number ( index = (doubletolongbits(...) >>> 52) & 0x7ff; ), but that's way beyond what is needed for this problem, since it's normally used when summing up a huge list of numbers. The array is initialized to zero, and each time a new number is to be added, the index for that number is generated. If array[index] == 0. , then the number is just stored, else number = number + array[index]; , array[index] = 0.; , and the process repeated until array[index] == 0. and the number stored (or until overflow is detected). Once all numbers have been added, then the array is summed from index = 0 to index = 0x3ff to produce the sum. The purpose of this is to only add numbers with the same exponent of 2.

Last edited: Nov 9, 2012
6. Nov 9, 2012

### Ibix

I don't think I can add to Mark44's post.

Then you'll have to think about how to round a number off (I don't recall whether or not Java does this natively - check Math, or Google for a solution).

...unless there's a rounding error. The wise programmer always assumes that floats and doubles are a little bit off the mark.

That's not what the results in your first post say. They have a rounding error such that timeArr[10]<0.5, which should cause an exception at the end of the populating loop.

7. Nov 9, 2012

### rcgldr

Based on testme's code, and allowing (int) to always round down (I assume that normally it just rounds to nearest integer):

array size = (int)(tmax/tstep) + 1 = 11 + 1 = 12.

If (tmax/tstep) is an exact integer, then the array size will be one larger than needed.

Last edited: Nov 9, 2012
8. Nov 10, 2012

### Ibix

No - taking the tmax/tstep=10 example from testme's last post, you need 11 array elements (0, 1, ... 10). If tmax/tstep were 9.999, he'd be short an element.

9. Nov 10, 2012

### rcgldr

Good catch. I missed the part about the first step starting at zero. Also I wasn't sure if Java (int) typecast truncates or rounds. C (int) typecast truncates. If it truncates like C, then it should be (int) ( (tmax/tstep) + 0.5) + 2 , since the for statement for(int i = 1; timeArr[i - 1] <= tMax; i++) could allow going a partial step beyond tmax. For example, if tmax = 10. and tstep = 3., then the for loop iterates i from 1 to 4, requiring the array size to be 5.

testme hasn't replied to this thread lately, so I don't know if he/she is still looking at this.

10. Nov 10, 2012

### testme

Thanks for all the replies but I figured out a secondary way that checks when the loop should stop which makes it work

instead of comparing when the last element in the array is tMax I compared when i < ((int)(tMax/tStep + 1))

11. Nov 10, 2012

### Ibix

I'd just use i<timeArr.length, if I were you. A good rule of thumb is never to calculate something twice. One, you save time (not a lot, in this case); two, if you need to change something you don't have to search through your code for it; three, someone coming to your code cold can instantly see that you're populating the whole array without having to do any calculation.

rcgldr: yeah, Java just truncates. I'm not aware of a language that rounds in a cast, but I haven't done a proper survey.

12. Nov 10, 2012

### rcgldr

I don't know Java or the other new languages (except for C / C++). For older languages like Pascal, cast is not a type conversion, just a re-interpetation of the bits without modification of those bits (no conversion) casting a float of 1.0 to integer makes it an integer = 0x3f800000. In C / C++, you can do this by casting via a pointer: * (int *) (&float_variable). Fortran has multiple float or double to integer type conversion functions, some that truncate, others that round.

Using timeArr.length as you mentioned would solve the problem. With C / C++, you could use (sizeof(timeArr) / sizeof(double)) to get the "length".

Last edited: Nov 10, 2012