2

I have a vector class (2D mathematical vector) with floats as its components.

For some intermediate calculations I have the choice of using doubles. Should I use the intermediate double precision as long as possible, only casting to float at the end, or is it better to cast any doubles back to floats as soon as possible?

For example, here are two possible implementations of the vector normalization.

First, keeping the double for all calculations:

public class Vector2f {    

    private float x;
    private float y;

    ....

    public Vector2f normalize() {
        double length = Math.sqrt((x * x) + (y * y));
        return new Vector2f(
                (float) (x / length),
                (float) (y / length)
        );
    }
}

Second, converting to float immediately:

public Vector2f normalize() {
    float length = (float) Math.sqrt((x * x) + (y * y));
    return new Vector2f(
            x / length,
            y / length
    );
}
jhyot
  • 3,733
  • 1
  • 27
  • 44
  • Generally speaking, it's always better to keep precision as long as possible, especially if your values are very small/close to zero. – Pavel S. Jul 09 '16 at 22:45
  • I guess it depends on the application and the values you have. But note that performance can suffer from constant conversions from float to double and back. You can only decide what is better for your application, by trying both and checking if the second version is good enough. – Rudy Velthuis Jul 09 '16 at 22:45
  • 1
    Unrelated, but note that if you keep on using double, you could do: `double factor = 1.0 / Math.sqrt((x * x) + (y * y)); ... new Vector2f(x * factor, y * factor);`. – Rudy Velthuis Jul 09 '16 at 22:48
  • @Rudy what is the advantage of calculating it like this? Better performance because of one division less? – jhyot Jul 10 '16 at 08:23
  • Yes, multiplication is quite a bit faster than division. – Rudy Velthuis Jul 10 '16 at 13:10

2 Answers2

4

Generally speaking, it's always better to keep precision as long as possible, especially if your values are very small/close to zero.

Try these lines:

System.out.println(0.00001f * 0.00002f / 0.00000003f);
System.out.println(0.00001d * 0.00002d / 0.00000003d);

The output will be:

0.0066666664
0.006666666666666668

Which one is better, what do you think? So, such errors may accumulate in your computations and affect your output.

To make it more funny:

System.out.println(0.00001f * 0.00002f * 0.00000003f* 0.00000003f* 0.00000003f* 0.00000003f* 0.00000003f * 0.00000003f / 0.00000003f / 0.00000003f / 0.00000003f / 0.00000003f/ 0.00000003f/ 0.00000003f);
System.out.println(0.00001d * 0.00002d * 0.00000003d* 0.00000003d* 0.00000003d* 0.00000003d* 0.00000003d * 0.00000003d / 0.00000003d / 0.00000003d / 0.00000003d / 0.00000003d/ 0.00000003d/ 0.00000003d);

and output:

0.0
2.0000000000000003E-10

Be careful with small values!

Pavel S.
  • 1,267
  • 14
  • 19
0

Result of casting from double to float in end will be more accurate than casting it before these operation.

         x / length,
         y / length

Solution one is seems better than other one.

shivam
  • 511
  • 3
  • 13