繁体   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