0

When multiplying a floating point number that is very close to 1 with an int > 0, can it ever be interpreted as 1.

That is, if Math.random() returns its highest possible result (which is 1 step below 1.0), will

(int)(Math.random() * 8)

be 8 or 7?

For a practical example, can this often-used construct give an index out of bounds error:

someArray[(int)(Math.random() * someArray.length)];

I'm specifically interested in answers for Java and ActionScript 3, but I suppose they all use the same rules for floating point arithmetic, and answers for any platform would be useful.

Update: Though I already accepted an answer, I'd still appreciate confirmation that this can't go wrong in ActionScript 3 either, since a colleague reporting that he saw it go wrong once is what partly prompted me to ask this question.

Jennifer Canas
  • 109
  • 1
  • 8

3 Answers3

1

Because 8 is a power of 2, multiplying a float by it will never add or remove precision from the value unless you overflow. Multiplying by other numbers, and in particular floating point numbers (other than a negative power of 2, e.g. 0.25, 0.0625, etc.), will reduce precision.

Ignacio Vazquez-Abrams
  • 776,304
  • 153
  • 1,341
  • 1,358
0

Using Math.random in java (http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/Math.html) the value can be greater than or equal to 0.0 and less than 1.0.

Using one test with value 0.999999 the value of (int)(Math.random() * 8) is 8. You can test the experiment using the next code

public static void main(String args[]) {
        for (int i = 0; i <= 100; i++) {
            double frac1=0.999999999999999999 ;
            double frac=Math.random() ;
            int integer=(int) (frac*8);
            int integer1=(int) (frac1*8);
            System.out.println( integer+"-"+frac);
            System.out.println( integer1+"-"+frac);
        }
    }

But Math.random()*8 can return other values like 1,2,3,4,5,7 or 6 depends of the value returned for Math.random. You can test this running the sample code

Nauber
  • 21
  • 1
0

Actually a quick exhaustive search can show that this cannot happen for any 32bit integer with floats:

public static void main(String[] args) {
    int repr = Float.floatToIntBits(1f) - 1;
    float val = Float.intBitsToFloat(repr);
    for (long i = 1; i <= -(long)Integer.MIN_VALUE; i++) {
        if ((int) (val * i) == i) {
            System.out.println("FOUND VALUE: " + i);
        }
        if ((int) (val * -i) == -i) {
            System.out.println("FOUND VALUE: " + -i);
        }
        if (i % 100000000 == 0) {
            System.out.println("Done: " + (double)i/Integer.MAX_VALUE);
        }
    }
    // nothing printed
}
Voo
  • 29,040
  • 11
  • 82
  • 156