0

I'm trying to learn a bit on robotics and Java. In my attempt I have written a function that (should) take a uniformed array called q(0.2,0.2,0.2,0.2,0.2), multiply each value in this array by 0.6 or 0.2 based on value Z, compared to another array world (0,1,1,0,0) that represents hit or miss of value Z compared to array world and finally return a new uniformed array.

So: 1.) Loop through (0,1,1,0,0) 2.) if i!=Z than i*0.2, if i=Z than i*0.6 3.) sum all new values in q to a double called normalize 4.) normalize each value in q (value / normalize)

Below is the function:

    public static final double pHit = 0.6;
    public static final double pMiss = 0.2;
    public static int[] world = {0,1,1,0,0};
    public static List<Double> q = new ArrayList<Double>();

    public static List<Double> sense(int Z){
        double normalize = 0;
        for(int i=0;i < q.size();i++){
            if(Z == world[i]){
                q.set(i, (q.get(i) * pHit));
            }
            else{
                q.set(i, (q.get(i) * pMiss));
            }
        }
        //Normalize
        for(int i=0;i < q.size();i++){
            normalize += q.get(i);
        }
        for(int i=0;i<q.size();i++){
            q.set(i, q.get(i)/normalize);
        }
        return q;   
    }

If I set world to (0,1,0,0,0) and Z to 1 I get following results: 0.14285714285714288 0.4285714285714285 0.14285714285714288 0.14285714285714288 0.14285714285714288

This normalizes nicely (sum = 1).

But if I set world to (0,1,1,0,0) and Z to 1 I get a strange result: 0.1111111111111111 0.3333333333333332 0.3333333333333332 0.1111111111111111 0.1111111111111111

This "normalizes" to 0.9999999999999998 ?

Many thanks for any input!

user2826751
  • 15
  • 1
  • 4

3 Answers3

2

Doubles are not perfect representations of the real number line. They have only about 16 digits of precision. In successive computations, errors can build, sometimes catastrophically. In your case, this has not happened, so be happy.

The value of 0.1 is a nice example. In IEEE floating point, it has only an approximate representation. As a binary fraction, it is 0.0[0011] where the part in square braces repeats forever. This is why floating point numbers (including doubles) may not be the best choice for representing prices.

I highly suggest reading this classic summary:

http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html

Gene
  • 46,253
  • 4
  • 58
  • 96
  • Unfortunately I use this function over and over so it happened just what you wrote: a catastrophic error! :) So, if I understand correct, I'm stuck to using BigDecimal which will slow down my computations drastically? Anyone knows what python uses in this case? I have seen example of my code in python, but there it was not stated at all what kind of variable they were even using... – user2826751 Jan 27 '14 at 18:09
  • 1
    Do you really need results that are more precise that you can get with double? BigDecimal has the same problem. One third cannot be exactly represented in it. – Patricia Shanahan Jan 27 '14 at 21:37
  • 1
    @user2826751 No floating point representation will ever be perfect. Why on earth is an error in normalization of 0.0000000000000001 a problem? – Gene Jan 27 '14 at 22:34
  • NB Python in its default output mode does not print 16 decimal places as Java does, so it would have rounded to 1.0 or similiar. It's dealing with the same error internally. – Gene Jan 27 '14 at 22:45
0

Floating point numbers are not exactly represented on computers. For that reason you'll get very small fractions off from exact values when multiplying floating values together.

See this answer as it goes into more depth about floating representations and references this Floating-Point Arithmetic article.

Community
  • 1
  • 1
Pyrce
  • 8,296
  • 3
  • 31
  • 46
0

Welcome to the world of floating point numbers! I did not try to understand your code in detail, but the result 0.9999999999999998 is perfectly normal. I recommend you to read a bit about floating point numbers and their precision.

SebastianH
  • 2,172
  • 1
  • 18
  • 29