4

「任意の」正の浮動小数点数と呼ぶことにしたものを生成したいと思います。つまり、スケールに依存しない乱数 (つまり、対数が均一に分布する数) です。私はあまり数学者ではないので、私が求めているものには別の名前があるかもしれないことは知っています.

これが私の最初の素朴な解決策です:

import sys
import random

def arbitrary(min=sys.float_info.min_10_exp, max=sys.float_info.max_10_exp):
    return 10 ** random.uniform(min, max)

これはおそらく理想的ではないと思います.1つには、 の限られた精度random.uniform()と浮動小数点表現自体との間に何らかの相互作用があり、より高い桁数で予想される出力にバンチングとギャップが発生する可能性があると思います.

より良いアプローチはありますか?ランダムなビットの文字列を生成し、それを浮動小数点数に変換する方が理にかなっていますか?

編集: コメントで Oli Charlesworth が指摘したように、「ランダムなビットを float に変換する」というアイデアは、私が望むことを行いません (これは、log(n) の均一な分布です)。

4

1 に答える 1

1

あなたのアプローチがいくつかの数値を返さないことは正しいです。たとえば、 と の間に浮動小数点数はありません1.01.0000000000000002、で10**1.0000000000000002あり、と:と10.000000000000005の間に 2 つの数値があります。これらの 2 つの数値は、アルゴリズムによって返されることはありません。10.010.00000000000000510.00000000000000210.000000000000004

しかし、チートDecimalしてより正確にべき乗するために使用することができます:

>>> float(10 ** Decimal('1'))
10.0
>>> float(10 ** Decimal('1.0000000000000001'))
10.000000000000002
>>> float(10 ** Decimal('1.00000000000000015'))
10.000000000000004
>>> float(10 ** Decimal('1.0000000000000002'))
10.000000000000005

したがって、十分な精度のarbitraryランダムなDecimal指数を生成し、それらを指数として使用する必要があります。指数の精度が 2 進数で 64 桁で十分であると仮定すると、コードは次のようになります。

import sys, random
from decimal import Decimal

def _random_decimal(minval, maxval, added_prec):
    # generate a Decimal in the range [minval, maxval) with the
    # precision of additional ADDED_PREC binary digits
    rangelen = maxval - minval
    denom = rangelen << added_prec
    return minval + Decimal(rangelen) * random.randrange(denom) / denom

def arbitrary():
    min_exp = sys.float_info.min_exp - sys.float_info.mant_dig
    max_exp = sys.float_info.max_exp
    return float(2 ** _random_decimal(min_exp, max_exp, 64))
于 2013-07-06T22:06:43.413 に答える