2011-02-04 17 views
5

यह प्रश्न: How to generate a random BigInteger बिगइंटर के लिए Random.nextInt (int n) के समान अर्थशास्त्र को प्राप्त करने का एक तरीका बताता है।मैं जावा में एक यादृच्छिक BigDecimal कैसे बना सकता हूँ?

मैं BigDecimal और Random.nextDouble() के लिए ऐसा करना चाहता हूं।

उपरोक्त प्रश्न में एक उत्तर एक यादृच्छिक BigInteger बनाने और फिर एक यादृच्छिक पैमाने के साथ एक BigDouble बनाने का सुझाव देता है। एक बहुत ही त्वरित प्रयोग यह एक बहुत ही बुरा विचार :) होने के लिए पता चलता

मेरे अंतर्ज्ञान है कि इस पद्धति का उपयोग पूर्णांक की आवश्यकता होगी n-log10(R), जहां n में आवश्यक परिशुद्धता के अंकों की संख्या है जैसे कुछ द्वारा बढ़ाया जा रहा है आउटपुट और आर यादृच्छिक BigInteger है। इससे अंकों की सही संख्या मौजूद होनी चाहिए ताकि (उदाहरण के लिए) 1 -> 10^-64 और 10^64 -> 1.

स्केलिंग मूल्य को भी परिणामस्वरूप गिरने के लिए सही ढंग से चुना जाना चाहिए सीमा [0,1] में।

क्या किसी ने इससे पहले किया है, और क्या वे जानते हैं कि परिणाम सही तरीके से वितरित किए गए हैं या नहीं? क्या इसे हासिल करने का कोई बेहतर तरीका है?

संपादित करें: स्केल तर्क की मेरी समझ को सही करने के लिए @biziclop के लिए धन्यवाद। उपर्युक्त आवश्यक नहीं है, एक स्थिर पैमाने कारक वांछित प्रभाव है।

बाद में संदर्भ, मेरे (जाहिरा तौर पर काम कर कोड) के लिए है:

private static BigDecimal newRandomBigDecimal(Random r, int precision) { 
    BigInteger n = BigInteger.TEN.pow(precision); 
    return new BigDecimal(newRandomBigInteger(n, r), precision); 
} 

private static BigInteger newRandomBigInteger(BigInteger n, Random rnd) { 
    BigInteger r; 
    do { 
     r = new BigInteger(n.bitLength(), rnd); 
    } while (r.compareTo(n) >= 0); 

    return r; 
} 

उत्तर

3

यह निश्चित रूप से बहुत आसान है ... अगर मुझे केवल इतना पता था कि आप क्या चाहते हैं। रेंज [0, 1) और सटीक एन दशमलव अंकों में समान रूप से वितरित संख्या के लिए 10 * एन से कम एक समान BigInteger उत्पन्न करता है और इसे 10 * एन द्वारा स्केल करता है।

+0

यह मूल उत्तर का "यादृच्छिक पैमाने" हिस्सा था जो गलत था। यह विधि ठीक होनी चाहिए। – DJClayworth

+0

आप 10^एन से कम वर्दी बिगइंटर बना सकते हैं जो कई पूर्णांक बनाते हैं जो [0, 10^मीटर) हैं और उन्हें संयोजित करते हैं। –

+0

ठीक है, लेकिन इस प्रश्न की पहली वाक्य में जुड़े एक अच्छे उत्तर के साथ एक संबंधित प्रश्न है। आपका प्रस्ताव भी अच्छी तरह से काम कर सकता है, खासकर एम = 9 के साथ, random.nextInt() का उपयोग किया जा सकता है। – maaartinus

1

मैं यहाँ स्पष्ट लापता हो सकता है, लेकिन कैसे दो यादृच्छिक BigInteger रों एक अन्य आंशिक बनाने, पूर्णांक हिस्सा होने के लिए, और के बारे में ? जाहिर है कि "आंशिक" बिगिन की सीमा उस परिशुद्धता से निर्धारित की जाएगी जिसे आप अनुमति देना चाहते हैं, जिसे आप नीचे से दूर नहीं कर सकते हैं।

अद्यतन: इसे केवल एक यादृच्छिक bigint के साथ काम करने के लिए और अधिक सरल बनाया जा सकता है। यदि आप के दशमलव दशमलव (जहां के स्थिर है) के साथ 0 और n के बीच यादृच्छिक संख्या चाहते हैं, तो आप 0 और एन * 10^के बीच यादृच्छिक संख्या उत्पन्न करते हैं और इसे 10^के द्वारा विभाजित करते हैं।

+0

ऐसा करने का नतीजा समान रूप से वितरित नहीं किया जाता है। मैंने यह कोशिश की, और परिणाम समान रूप से आंशिक भाग में वितरित किया गया है, जिसका अर्थ है कि 10^-27 परिणाम में दिखाई देने के लिए 0.01 और 0.1 के बीच की संख्या के बराबर है। 10^-27 26 होना चाहिए या इतनी मात्रा के आदेश 0.1-0.01 –

+0

@ माइक ह्यूस्टन में किसी संख्या की तुलना में दिखाई देने की संभावना कम है, इसलिए मुझे तब भी याद आ रही है, क्योंकि मुझे अभी भी यह नहीं मिला है।क्या आप इसे समान रूप से वितरित करना चाहते हैं या नहीं? – biziclop

+0

@ माइक ह्यूस्टन नोप, अभी भी इसे प्राप्त नहीं है। यदि आप समान रूप से वितरित चर लेते हैं जो अधिकतर अंकों पर लंबा होता है और आप इसे 10^n तक विभाजित करते हैं, तो यह अभी भी समान रूप से वितरित होता है। – biziclop

2

मैंने एक यादृच्छिक BigInteger Andy Turner's answer about generating a random BigInteger उत्पन्न करने के बारे में एक पोस्ट बनाया है। मैं एक यादृच्छिक BigDecimal उत्पन्न करने के लिए सीधे इसका उपयोग नहीं करता। अनिवार्य रूप से मेरी चिंता एक अंक में प्रत्येक अंक उत्पन्न करने के लिए रैंडम के स्वतंत्र उदाहरणों का उपयोग करना है। एक समस्या मैंने देखी है कि यादृच्छिकता के साथ केवल एक ही पंक्ति के बहुत से मूल्य और विशेष संख्या हैं जो आप पंक्ति में प्राप्त करते हैं। इसके अलावा पीढ़ी जेनरेट किए गए मूल्यों के वितरण के कुछ भी बनाए रखने की कोशिश करती है। मेरा समाधान किसी सरणी या यादृच्छिक उदाहरणों के संग्रह को संग्रहीत करने और इन्हें कॉल करने पर निर्भर करता है। मुझे लगता है कि यह इसके बारे में जाने का एक अच्छा तरीका है और मैं यह पता लगाने की कोशिश कर रहा हूं, इसलिए अगर किसी के पास इस दृष्टिकोण का कोई संकेत या आलोचना है तो मुझे दिलचस्पी है।

/** 
* 
* @param a_Random 
* @param decimalPlaces 
* @param lowerLimit 
* @param upperLimit 
* @return a pseudo randomly constructed BigDecimal in the range from 
* lowerLimit to upperLimit inclusive and that has up to decimalPlaces 
* number of decimal places 
*/ 
public static BigDecimal getRandom(
     Generic_Number a_Generic_Number, 
     int decimalPlaces, 
     BigDecimal lowerLimit, 
     BigDecimal upperLimit) { 
    BigDecimal result; 
    BigDecimal range = upperLimit.subtract(lowerLimit); 
    BigDecimal[] rangeDivideAndRemainder = 
      range.divideAndRemainder(BigDecimal.ONE); 
    BigInteger rangeInt = rangeDivideAndRemainder[0].toBigIntegerExact(); 
    BigInteger intComponent_BigInteger = Generic_BigInteger.getRandom(
      a_Generic_Number, 
      rangeInt); 
    BigDecimal intComponent_BigDecimal = 
      new BigDecimal(intComponent_BigInteger); 
    BigDecimal fractionalComponent; 
    if (intComponent_BigInteger.compareTo(rangeInt) == 0) { 
     BigInteger rangeRemainder = 
       rangeDivideAndRemainder[1].toBigIntegerExact(); 
     BigInteger fractionalComponent_BigInteger = 
       Generic_BigInteger.getRandom(a_Generic_Number, rangeRemainder); 
     String fractionalComponent_String = "0."; 
     fractionalComponent_String += fractionalComponent_BigInteger.toString(); 
     fractionalComponent = new BigDecimal(fractionalComponent_String); 
    } else { 
     fractionalComponent = getRandom(
       a_Generic_Number, decimalPlaces); 
    } 
    result = intComponent_BigDecimal.add(fractionalComponent); 
    result.add(lowerLimit); 
    return result; 
} 

/** 
* Provided for convenience. 
* @param a_Generic_BigDecimal 
* @param decimalPlaces 
* @return a random BigDecimal between 0 and 1 inclusive which can have up 
* to decimalPlaces number of decimal places 
*/ 
public static BigDecimal getRandom(
     Generic_Number a_Generic_Number, 
     int decimalPlaces) { 
    //Generic_BigDecimal a_Generic_BigDecimal = new Generic_BigDecimal(); 
    Random[] random = a_Generic_Number.get_RandomArrayMinLength(
      decimalPlaces); 
    //System.out.println("Got Random[] size " + random.length); 
    String value = "0."; 
    int digit; 
    int ten_int = 10; 
    for (int i = 0; i < decimalPlaces; i++) { 
     digit = random[i].nextInt(ten_int); 
     value += digit; 
    } 
    int length = value.length(); 
    // Tidy values ending with zero's 
    while (value.endsWith("0")) { 
     length--; 
     value = value.substring(0, length); 
    } 
    if (value.endsWith(".")) { 
     value = "0"; 
    } 
    BigDecimal result = new BigDecimal(value); 
    //result.stripTrailingZeros(); 
    return result; 
} 
+0

मुझे समझ में नहीं आता है कि "रैंडम के साथ आप [ए] विशेष संख्या के बहुत से मूल्य हैं जो आपको एक पंक्ति में मिलता है"। रैंडम के लिए जावा स्रोत के अनुसार, "अगला का सामान्य अनुबंध यह है कि यह एक int मान देता है और यदि तर्क बिट्स 1 और 32 (समावेशी) के बीच है, तो लौटाए गए मूल्य के बहुत कम ऑर्डर बिट्स होंगे .. स्वतंत्र रूप से चुने गए बिट मान, जिनमें से प्रत्येक ... समान रूप से 0 या 1 होने की संभावना है। " ऐसा लगता है कि मुझे यह संकेत मिलता है कि एक पंक्ति में आपको कितने समान मूल्य मिलते हैं, इसकी कोई सीमा नहीं है, यह अपेक्षाकृत असंभव है, जैसा कि आप उम्मीद करेंगे। –

संबंधित मुद्दे