2011-03-11 13 views
5

मेरे पास एक enum है कि मैं यादृच्छिक रूप से एक मान का चयन करना चाहता हूं, लेकिन वास्तव में यादृच्छिक नहीं। मैं कुछ मूल्यों को अब तक चुनने की संभावना कम करना चाहता हूं। यहां मेरे पास अब तक है ...संभावना के साथ enum से यादृच्छिक मूल्य

private enum Type{ 
     TYPE_A, TYPE_B, TYPE_C, TYPE_D, TYPE_E; 

     private static final List<Type> VALUES = 
      Collections.unmodifiableList(Arrays.asList(values())); 
      private static final int SIZE = VALUES.size(); 
      private static final Random RANDOM = new Random(); 

      public static Type randomType() { 
      return VALUES.get(RANDOM.nextInt(SIZE)); 
      } 
    } 

क्या इन मूल्यों में से प्रत्येक को संभावनाएं असाइन करने का कोई प्रभावी तरीका है?

कोड से here

उत्तर

6

कई तरीके के लिए यह उनमें से एक है, इसी तरह करने के लिए, अपने दृष्टिकोण

private enum Type{ 
    TYPE_A(10 /*10 - weight of this type*/), TYPE_B(1), TYPE_C(5), TYPE_D(20), TYPE_E(7); 

private int weight; 

private Type(int weight) { 
    this.weight = weight; 
} 

private int getWeight() { 
    return weight; 
} 


    private static final List<Type> VALUES = 
     Collections.unmodifiableList(Arrays.asList(values())); 

    private int summWeigts() { 
     int summ = 0; 
     foreach(Type value: VALUES) 
      summ += value.getWeight(); 
     return summ; 
    } 
    private static final int SIZE = summWeigts(); 
    private static final Random RANDOM = new Random(); 

    public static Type randomType() { 
     int randomNum = RANDOM.nextInt(SIZE); 
     int currentWeightSumm = 0; 
     for(Type currentValue: VALUES) { 
      if (randomNum > currentWeightSumm && 
       randomNum <= (currentWeightSumm + currentValue.getWeight()) { 
      break; 
      } 
      currentWeightSumm += currentValue.getWeight(); 
     } 

     return currentValue.get(); 
    } 
} 
+0

मुझे लगता है कि आपको गलत समझा जाता है। आइडिया है - आप सभी वजन को सारांशित करते हैं। अब अधिकतम = गणना मूल्य के साथ शासक कल्पना करें। अब इस नियम पर प्रत्येक वजन को डैश करें, तो पहले (उत्तर में मेरे उदाहरण के अनुसार) 0 से 10, दूसरा 10 से 11, त्रिज्या 11 से 16 और इसी तरह होगा। अब अपनी उंगली को हमारे शासक के यादृच्छिक स्थान पर इंगित करें और देखें कि आप किस सेगमेंट को इंगित करते हैं। संपादित उत्तर –

+0

वास्तव में यह है कि मैं क्या कर रहा था। धन्यवाद! – tgrosinger

+0

बीटीडब्ल्यू अगर आप कन्स्ट्रक्टर में टाइप की सटीक सीमाएं टाइप करते हैं तो आप परफॉर्मेंस में सुधार कर सकते हैं, लेकिन पांच प्रकारों पर यह वास्तविक नहीं है। –

0

पाया यहाँ यादृच्छिक पर एक enum मूल्य चुनने के लिए एक क्रियाशील approach है। आप here सुझाए गए अनुसार संभाव्यताओं को समायोजित कर सकते हैं।

0

मान लें कि आपके पास मूल्यों की सीमित संख्या है, जिसमें प्रत्येक मान के लिए वजन के एक अलग सरणी (फ्लोट [] वजन;) हो सकती है। ये मान 0 और 1 के बीच होंगे। जब आप एक यादृच्छिक मान का चयन करते हैं तो एक और यादृच्छिक संख्या उत्पन्न होती है और केवल उस मान का चयन करें यदि दूसरा जेनरेट किया गया नंबर उस मान के वजन से नीचे है।

0

आप एक कस्टम निर्माता provding bby जुड़े डेटा के साथ एक enum बना सकते हैं और संभावनाओं के लिए weightings आवंटित करने के लिए निर्माता का उपयोग और उसके बाद

public enum WeightedEnum { 
    ONE(1), TWO(2), THREE(3); 
    private WeightedEnum(int weight) { 
     this.weight = weight; 
    } 
    public int getWeight() { 
     return this.weight; 
    } 
    private final int weight; 

    public static WeightedEnum randomType() { 
     // select one based on random value and relative weight 
    } 
} 
0
import java.util.*; 
enum R { 
    a(.1),b(.2),c(.3),d(.4); 
    R(final double p) { 
     this.p=p; 
    } 
    private static void init() { 
     sums=new double[values().length+1]; 
     sums[0]=0; 
     for(int i=0;i<values().length;i++) 
      sums[i+1]=values()[i].p+sums[i]; 
     once=true; 
    } 
    static R random() { 
     if (!once) init(); 
     final double x=Math.random(); 
     for(int i=0;i<values().length;i++) 
      if (sums[i]<=x&&x<sums[i+1]) return values()[i]; 
     throw new RuntimeException("should not happen!"); 
    } 
    static boolean check() { 
     double sum=0; 
     for(R r:R.values()) 
      sum+=r.p; 
     return(Math.abs(sum-1)<epsilon); 
    } 
    final double p; 
    static final double epsilon=.000001; 
    static double[] sums; 
    static boolean once=false; 
} 
public class Main{ 
    public static void main(String[] args) { 
     if (!R.check()) throw new RuntimeException("values should sum to one!"); 
     final Map<R,Integer> bins=new EnumMap<R,Integer>(R.class); 
     for(R r:R.values()) 
      bins.put(r,0); 
     final int n=1000000; 
     for(int i=0;i<n;i++) { 
      final R r=R.random(); 
      bins.put(r,bins.get(r)+1); 
     } 
     for(R r:R.values()) 
      System.out.println(r+" "+r.p+" "+bins.get(r)/(double)n); 
    } 
} 
+0

मुझे मुख्य विधि में किए गए सामान को समझ में नहीं आता है। लगता है कि @AlexeySviridov द्वारा प्रस्तावित विधि की तुलना में बहुत अधिक दृढ़ हो गया है, जिसे मैंने थोड़ा और सरल बनाया है। – tgrosinger

+0

यादृच्छिक रूप से अभ्यास करने के लिए बस कुछ कोड और देखें कि वितरण कैसा दिखता है। –

0

यहाँ एक और विकल्प है जो वितरण कार्यावधि में निर्दिष्ट करने की अनुमति देता है।

एलेक्सी Sviridov से सुझाव शामिल है। इसके अलावा विधि यादृच्छिक() कई विकल्प हैं जब टेड डनिंग से सुझाव शामिल कर सकते हैं।

 private enum Option { 

     OPTION_1, OPTION_2, OPTION_3, OPTION_4; 
     static private final Integer OPTION_COUNT = EnumSet.allOf(Option.class).size(); 
     static private final EnumMap<Option, Integer> buckets = new EnumMap<Option, Integer>(Option.class); 
     static private final Random random = new Random(); 
     static private Integer total = 0; 

     static void setDistribution(Short[] distribution) { 
      if (distribution.length < OPTION_COUNT) { 
       throw new ArrayIndexOutOfBoundsException("distribution too short"); 
      } 
      total = 0; 
      Short dist; 
      for (Option option : EnumSet.allOf(Option.class)) { 
       dist = distribution[option.ordinal()]; 
       total += (dist < 0) ? 0 : dist; 
       buckets.put(option, total); 
      } 
     } 

     static Option random() { 
      Integer rnd = random.nextInt(total); 
      for (Option option : EnumSet.allOf(Option.class)) { 
       if (buckets.get(option) > rnd) { 
       return option; 
       } 
      } 
      throw new IndexOutOfBoundsException(); 
     } 
    } 
संबंधित मुद्दे