给定最小值、最大值、平均值和标准差,使用 Java 从分布中生成随机值

Posted

技术标签:

【中文标题】给定最小值、最大值、平均值和标准差,使用 Java 从分布中生成随机值【英文标题】:Given a min, max, mean and standard deviation, generate a random value from a distribution using Java 【发布时间】:2021-12-22 21:52:12 【问题描述】:

鉴于 min = 0.00,max = 1400.00,mean = 150.50,标准差 = 25.00,如何根据这些统计数据生成随机值?据我了解,该图是一个倾斜图,但是我不太确定它是否是对数正态分布的。但是,据我目前的理解,以下代码返回一个来自正态分布的值。

private static int generateValue(double mean, double stdDev) 
    return (rand.nextGaussian() * stdDev) + mean);

【问题讨论】:

这是一个统计建模问题,而不是编程问题。您的分布既不能是正态分布也不能是对数正态分布,因为它们都有无限的支持,并且您指定了有限的最小值和最大值。您需要确定一个能够同时满足所有四个约束的分布,这是不平凡的并且可能不可行。示例:我们可以排除三角分布,因为mean = (min + mode + max) / 3。使用您的约束求解模式会产生 -948.5,但模式必须是介于最小值和最大值之间的值,因此不存在这样的三角形。 明白,但是,鉴于以上这些值,有没有办法正确获取随机生成的值? 不知道要从哪个发行版生成。这就是为什么我说“你需要确定一个分布......” 嗨@pjs,鉴于分布是连续分布,有可能吗? 找到了一种使用缩放的 beta 发行版的方法。在过去的 15 年里,我不是 java 人(甚至没有在我的系统上安装它),但如果你有兴趣,我可以用 python 解释。 【参考方案1】:

一种方法是找到一个自然有界分布,该分布具有由两个参数表征的均值和方差。这将问题从试图同时满足四个约束(最小值、最大值、平均值和 s.d.)减少到根据两个参数求解两个方程(平均值和 s.d.)。 beta distribution 满足这些需求。它是在 [0, 1] 范围内定义的,但是可以通过将结果缩放 1400 来轻松调整到您的问题。我使用上面提供的 Wikipedia 链接来刷新我对 beta 均值和方差公式的记忆,然后前往Wolfram|Alpha 的求解器,使用平均值 150.5/1400 和标准差 25/1400 输入公式。这产生了 α=32.237057 和 β=267.642543 的解,因此您可以通过使用派生参数值生成值 X = 1400 * beta(α, β) 来满足您的要求。

我已经超过 15 年没有使用 Java 并且没有在我的机器上安装它,所以我使用 python 对其进行了测试以确认参数化:

from scipy.stats import beta
import math

a = 32.237057
b = 267.642543
n = 100_000_000

mean, var = beta.stats(a, b, moments='mv')
print( f"mean = mean * 1400, std dev = math.sqrt(var) * 1400" )

产生

平均值 = 150.50000000000003,标准差 = 25.000000000000004

我会说这与使用浮点运算的要求差不多。然后我尝试了实际的生成:

r = beta.rvs(a, b, size=n) * 1400
print( f"For n=n min and max are min(r) and max(r), respectively")

带输出:

对于 n=100000000,最小值和最大值分别为 45.22697720545599 和 327.87270125710194

您可能认为经验最大值较低,但请注意,1400 仅比平均值高 50σ。 Chebyshev's inequality 给出了一个非常弱的非参数上限,用于获得这样一个值的概率——它小于 1/2500。在许多情况下,包括这一次,实际概率远小于切比雪夫的界限。也就是说,得到接近1400的结果的概率基本上为零。

通过 Apache Commons 库可以通过 Google 快速搜索找到类 BetaDistribution,因此您应该可以直接将此方法映射到 Java。

【讨论】:

嗨@pjs,我非常感谢您的详尽解释。我将查看您提供的链接并使用 BetaDistribution 来解决我的问题。非常感谢【参考方案2】:

您可以使用 do while 或 just while 循环,然后您可以简单地使用 if 语句为您的数字设置参数并生成一个随机数!

import java.util.Random;
class GenerateRandom 
public static void main( String args[] ) 
  Random rand = new Random(); //instance of random class
  int upperbound = 25;
    //generate random values from 0-24
  int int_random = rand.nextInt(upperbound); 
  double double_random=rand.nextDouble();
  float float_random=rand.nextFloat();
  
  System.out.println("Random integer value from 0 to" + (upperbound-1)       + " : "+ int_random);
  System.out.println("Random float value between 0.0 and 1.0 :  "+float_random);
  System.out.println("Random double value between 0.0 and 1.0 : "+double_random);

【讨论】:

谢谢,但这段代码是用于正常生成随机数,我正在查看的是对数正态分布值

以上是关于给定最小值、最大值、平均值和标准差,使用 Java 从分布中生成随机值的主要内容,如果未能解决你的问题,请参考以下文章

R语言使用psych包的describeBy函数计算不同分组(group)的描述性统计值(样本个数均值标准差中位数剔除异常均值最小最大值数据范围极差偏度峰度均值标准差等)

最大值,最小值,平均值,标准差的计算

js 算数组平均值最大值最小值偏差标准差中位数数组从小打大排序上四分位数下四分位数

离差标准化

如何使用sql函数平均值总数最小值最大值

平均数、中位数、众数、方差、标准差、极差要怎么计算