簡體   English   中英

具有左偏或右偏的鍾形曲線

[英]Bell curve with left or right bias

在 Java 中,我想生成一個從 1 到 100 的隨機數,該隨機數可以基於刻度的任一端,同時仍然有可能來自另一端的數字仍然被“滾動”。

澄清一下,在正常情況下,在1 - 100 的卷數上,平均值為 50 ,但在某些情況下,我希望平均值下降到 25%。 但是仍然有機會產生 100%。

我看過 Random.nextGaussian,它確實改變了鍾形曲線,但對於低端值,這消除了高端可能性。

我應該使用什么公式或公式組合?

Bell_curve_with_shift

在此處輸入圖像描述

  1. 計算出所需的確切分發形式。

  2. 計算該分布的分位數函數。

  3. 使用適當的生成器在[0,1)中繪制一個統一的隨機數。

  4. 那就是分位數功能的輸入。

結果編號將根據需要分配。

想出了一些簡單的方法來至少接近這樣的結果。 我有點沒能掌握這一切背后的數學原理,所以我主要是通過反復試驗得出這個結論,當我得到一些看起來足夠好的東西時,我就結束了。

找到了兩種方法:

  1. 基本上創建三角分布,然后用簡單的指數調整它的值。 它創建了一個類似於鍾形曲線的形狀,但它在峰值處有一個尖銳的尖峰,而不是一個沉悶的尖峰。 通過改變指數,接近峰值的曲線可以是凹的也可以是凸的。

    三角指數

     /** * @param min lower bound * @param max upper bound * @param avg mode <min, max> * @param exp convex (0, 0.5> or concave <0.5, 1> or linear (0.5) */ public static double triangleExponential(double min, double max, double avg, double exp) { if (min >= max || avg < min || avg > max) { throw new IllegalArgumentException(); } double pivot = MathUtils.range(avg, min, max, 0, 1); double x = generator.nextUniform(0, 1); double nx; if (x < pivot) { nx = MathUtils.range(x, 0, pivot, 0, 1); nx = Math.pow(nx, exp); nx = MathUtils.range(nx, 0, 1, 0, pivot); } else { nx = MathUtils.range(x, pivot, 1, 0, 1); nx = 1 - Math.pow(nx, exp); nx = MathUtils.range(nx, 0, 1, pivot, 1); } return MathUtils.range(nx, 0, 1, min, max); }
  2. 第二種方法只是采用高斯分布並根據需要擠壓/拉伸它。

    壓扁高斯

     /** * @param min lower bound * @param max upper bound * @param avg mode <min, max> * @param exp 'peak sharpness' (0, 2> */ public static double squishedGaussian(double min, double max, double avg, double exp) { if (min >= max || avg < min || avg > max) { throw new IllegalArgumentException(); } double pivot = MathUtils.range(avg, min, max, 0, 1); double uniform = generator.nextUniform(0, 1); double x = generateGaussian(); if (uniform < pivot) { x = Math.pow(x, exp); x = MathUtils.range(x, 0, 1, 0, pivot); } else { x = 1 - (Math.pow(x, exp)); x = MathUtils.range(x, 0, 1, pivot, 1); } return MathUtils.range(x, 0, 1, min, max); } static double generateGaussian() { double gaussianMax = 5; //Its more like 5.4 double rand; do { rand = Math.abs(generator.nextGaussian(0, 1)); } while (rand > gaussianMax); return 1 - MathUtils.range(rand, 0, gaussianMax, 0, 1); }

MathUtils.range只是一個重新映射 function 的值范圍

    public static double range(double OldValue, double OldMin, double OldMax, double NewMin, double NewMax) {
        return (((OldValue - OldMin) * (NewMax - NewMin)) / (OldMax - OldMin)) + NewMin;
    }

generator是來自org.apache.commons.math3.randomRandomDataGenerator class

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM