如何在Java中创建随机的BigDecimal?

如何在Java中创建随机的BigDecimal?,java,math,random,biginteger,bigdecimal,Java,Math,Random,Biginteger,Bigdecimal,这个问题:描述了一种实现与大整数的Random.nextInt(intn)相同语义的方法 我想对BigDecimal和Random.nextDouble()执行同样的操作 上述问题的一个答案是,创建一个随机的BigInteger,然后用随机比例从中创建一个BigDouble。一个非常快速的实验表明这是一个非常糟糕的主意:) 我的直觉是,使用这种方法需要将整数按类似于n-log10(R)的方式进行缩放,其中n是输出中所需的精度位数,R是随机大整数。这应该允许出现正确的位数,以便(例如)1->10^

这个问题:描述了一种实现与大整数的Random.nextInt(intn)相同语义的方法

我想对BigDecimal和Random.nextDouble()执行同样的操作

上述问题的一个答案是,创建一个随机的BigInteger,然后用随机比例从中创建一个BigDouble。一个非常快速的实验表明这是一个非常糟糕的主意:)

我的直觉是,使用这种方法需要将整数按类似于
n-log10(R)
的方式进行缩放,其中n是输出中所需的精度位数,R是随机大整数。这应该允许出现正确的位数,以便(例如)1->10^-64和10^64->1

还需要正确选择缩放值,以使结果在[0,1]范围内

以前有人这样做过吗?他们知道结果是否正确分布吗?有没有更好的方法来实现这一点

编辑:感谢@biziclop纠正了我对scale参数的理解。不需要上述内容,恒定的比例因子具有所需的效果

供以后参考,我的(显然是工作代码)是:


我可能忽略了这里显而易见的内容,但是创建两个随机的
biginger
s怎么样,一个是整数部分,另一个是小数部分?显然,“分数”bigint的范围将由您想要允许的精度决定,这是您无法摆脱的


更新:这可以进一步简化为只使用一个随机bigint。如果想要一个精度为k的0到n之间的随机数(其中k是一个常数),只需生成一个0到n*10^k之间的随机数,并将其除以10^k即可

这当然很容易。。。要是我知道你想要什么就好了。对于范围内的均匀分布数[0,1)和精度为N的十进制数字生成一个小于10*N的统一BigInteger,并将其缩小10*N。

我发表了一篇关于生成随机BigInteger的帖子。我不会直接将其用于生成随机BigDecimal。本质上,我关心的是使用随机的独立实例来生成数字中的每个数字。我没有一个问题iced是指使用Random时,一行中只有这么多的值和特定的数字。同时,生成尝试保持生成值的均匀分布。我的解决方案取决于存储一个数组或随机实例集合并调用这些实例。我认为这是一种很好的方法,我我正在努力寻找答案,所以如果有人对这种方法有任何建议或批评,我很感兴趣

/**
 *
 * @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;
}
/**
*
*@param a_随机
*@param decimalPlaces
*@param lowerLimit
*@param上限
*@返回一个伪随机构造的BigDecimal,范围为
*下限到上限(含上限),最多有小数位数
*小数位数
*/
公共静态BigDecimal getRandom(
通用号一个通用号,
整数小数位数,
大十进制lowerLimit,
大十进制上限){
大十进制结果;
BigDecimal范围=上限。减法(下限);
BigDecimal[]范围分割和维护器=
range.divideandMainder(BigDecimal.ONE);
BigInteger rangeInt=RangeDivideAndMainder[0]。ToBiginGeteExact();
BigInteger intComponent\u BigInteger=Generic\u BigInteger.getRandom(
通用编号,
rangeInt);
BigDecimal intComponent_BigDecimal=
新的BigDecimal(intComponent_BigInteger);
大小数分式分量;
如果(intComponent_BigInteger.compareTo(rangeInt)==0){
大整数范围余数=
RangeDivideAndMainder[1]。ToBigintereExact();
BigInteger分馏组件\u BigInteger=
Generic\u biginger.getRandom(一个\u Generic\u数,rangerements);
字符串分馏组件\u String=“0。”;
分馏组件_字符串+=分馏组件_BigInteger.toString();
分馏组件=新的BigDecimal(分馏组件_字符串);
}否则{
分馏成分=getRandom(
a_通用_编号,小数点);
}
结果=intComponent\u BigDecimal.add(分馏成分);
结果。添加(下限);
返回结果;
}
/**
*为方便而提供的。
*@param a_Generic_BigDecimal
*@param decimalPlaces
*@返回一个介于0和1之间(含0和1)的随机BigDecimal,该值最多可包含
*小数位数
*/
公共静态BigDecimal getRandom(
通用号一个通用号,
整数(小数点){
//泛型_BigDecimal a_泛型_BigDecimal=新泛型_BigDecimal();
Random[]Random=a_Generic_Number.get_randomaryMinLength(
小数位数);
//System.out.println(“获得随机[]大小”+随机长度);
字符串值=“0。”;
整数位数;
int-ten_int=10;
for(int i=0;i
这样做的结果不是均匀分布的。我尝试了这个方法,结果是均匀分布在分数部分,这意味着10^-27与0.01到0.1之间的数字一样可能出现在结果中。10^-27应该比0.1到0.01之间的数字少出现26个数量级左右@Mike Houston我忽略了显而易见的事实,因为我仍然不明白。你希望它是均匀分布的还是不均匀分布的?@Mike Houston不,仍然不明白。如果你取一个均匀分布的变量,那就是
/**
 *
 * @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;
}