2013-07-06 70 views
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) 

這讓我覺得,這可能是不理想的:一兩件事,我想有可能是random.uniform()有限的精度和浮點之間的相互作用代表本身會導致更高數量級的預期產出的聚集和差距。

有沒有更好的方法? 只需生成一串隨機位,然後將其轉換爲它們表示的浮點數就更合理了嗎?

編輯:正如評論所指出的奧利查爾斯沃思,「隨機位轉換爲浮動」的想法並沒有做我想做的(這是日誌的均勻分佈(N))。

+2

後一種方法將不起作用; PDF將是分段平坦的,在每次冪爲2時採用一步。 –

回答

1

你是對的,你的方法不會返回一些數字。例如,有1.01.0000000000000002之間沒有浮點數字,但10**1.000000000000000210.000000000000005,並且有10.010.000000000000005之間兩個數字:10.00000000000000210.000000000000004。這兩個數字永遠不會被您的算法返回。

但是你可以欺騙和使用Decimal以更高的精度來exponentiate:

>>> 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指數並把它們作爲指數。假設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)) 
+0

使用'Decimal'來克服精度限制是一個巧妙的技巧,當然,將這種方法擴展到使用負指數也很簡單。謝謝! –

+0

@ZeroPiraeus一分鐘前我已將它擴展爲負指數,請重新加載。 :) – user4815162342