开发者

Can 0.99999999999 be rounded to 1.0 when multiplying?

开发者 https://www.devze.com 2023-04-12 17:28 出处:网络
When multiplying a floating point number that is very close to 1 with an int > 0, can it ever be interpreted as 1.

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 thi开发者_JS百科s 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.


If you multiply the greatest value below 1.0 with someInt (> 0), the result will never be someInt.

This can be exhaustively tested for integers like this:

Double greatestLessThanOne = Double.longBitsToDouble(4607182418800017407L);

// Assert that greatestLessThanOne is indeed the largest double less than 1.
//assert 1.0 == greatestLessThanOne + Math.ulp(greatestLessThanOne);

for (int i = 1; i >= 0; i++)
    if ((int) (greatestLessThanOne * i) == i)
        System.out.println("Exception found: " + i);

The snippet produces no output.

(Math.ulp returns the distance between the given double and the double value next larger in magnitude. The assertion thus ensures that greatestLessThanOne is indeed the greatest value less than 1.0.)

In other words, your line

Object element = elementArray[(int)(Math.random() * elementArray.length)];

will never give rise to an ArrayIndexOutOfBoundsException.


Furthermore, according to Mark Dickinsons comment over here, this holds also when multiplying with a double.

With IEEE 754 floating-point arithmetic in round-to-nearest mode, you can show that x * y < y for any x < 1.0 and any non-tiny positive y. (It can fail if y is either subnormal or the smallest positive normal number.)


Just round it, may be like this :

BigDecimal bd = new BigDecimal(Double.toString(d));
bd = bd.setScale(decimalPlace,BigDecimal.ROUND_HALF_UP);
0

精彩评论

暂无评论...
验证码 换一张
取 消