2011-10-11 9 views
36

整数> 0と1に非常に近い浮動小数点数を乗算し、これまでMath.random()が(1.0以下の1つのステップである)最高の可能な結果を​​返す場合、1である掛け算時に0.99999999999を1.0に丸めることができますか?

として解釈することができますwill

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

8または7ですか?

実用例えば

、この頻繁に使用される構築物は、境界エラーのうちの指標を与えることができます:

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

私は、JavaとActionScript 3のための答えでは特に興味が、私は彼らがすべて使用と仮定します浮動小数点演算のための同じルール、および任意のプラットフォームに対する答えが有用であろう。

更新:私はすでに答えを受け入れたものの、彼はそれが一度間違って行くのを見たことを報告して同僚の一部に私を促したものですから、私はまだ、これはどちらかのActionScript 3で間違って行くことができないことの確認をいただければと思いますこの質問をしてください。

+0

...しかし、私は待っていますより良い答え... – bdares

+4

@UdoFholl公式の数学的表記法を使用するつもりはなく、数多くの数を持つ数字を示したかっただけです。 –

+0

* 1に非常に近い浮動小数点数を掛けるときは、1 *と解釈することはできますか? - はい、0で乗算すると、;-) JK – aioobe

答えて

44

1.0より大きい最大値にsomeInt(> 0)を掛けた場合、結果は決してsomeIntになりません。

これは徹底的にこのような整数を試験することができる。

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); 

スニペットは、出力を生成しません。すなわち

Math.ulpダブル与えられ、大きさが大きい次double値との間の距離を返す。アサーションは、このようgreatestLessThanOneが実際に1.0未満の最大値であることを保証する。)

、あなたのライン

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

は、ArrayIndexOutOfBoundsExceptionを発生させません。二重に掛けるとき


さらに、here以上のマークDickinsonsのコメントによると、これも成り立ちます。

ちょうどそれラウンド

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.)

+2

良い答え。また、[Java](http://java.sun.com/docs/books/jls/third_edition/html/typesValues.html)は、最も近い値に丸めて使用します。「Javaプログラミング言語では、浮動小数点演算が不正確な結果は無限に正確な結果に最も近い表現可能な値に丸められなければならず、2つの最も近い表現可能な値が等しく近い場合には、最下位ビットがゼロのものこれは、IEEE 754標準のデフォルト丸めモードで** **最も近い丸め**と呼ばれます。 –

+1

Javaの優れた教訓をお寄せいただきありがとうございます+1 – mKorbel

+0

ほとんどのプラットフォームはIEEE 754に準拠しているため、この回答を受け入れています。ActionScript 3/Flashもそうであるかどうかは分かりますか?私はそれが実際そこで間違って行くことができるという噂を聞いた。 –

-2

、このようなことがあります。そのような数は* *次のintにオーバーフローしたことがない場合、私はかなり驚かれることと思います

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

' BigDecimal'?これはあまりにも頻繁に実行されるかもしれない単純なステートメントに対しては、かなり高価な "修正"(実際に必要な場合)です。 –

+1

これは単なる高価ではなく、ランダム分布の統計的特性にとっても問題です。 – leftaroundabout

+0

いいえ、私はそれが単なる例であることを意味し、bigdecimalより小さい他のオブジェクト型を使うことができます –