How can I create a random BigDecimal in Java?

后端 未结 3 544
旧时难觅i
旧时难觅i 2021-01-05 17:19

This question: How to generate a random BigInteger describes a way to achieve the same semantics as Random.nextInt(int n) for BigIntegers.

I would like to do the sam

相关标签:
3条回答
  • 2021-01-05 17:40

    I might be missing the obvious here but how about creating two random BigIntegers, one being the integer part, and the other the fractional? Obviously the range of the "fractional" bigint would be dictated by the precision you want to allow, which you can't get away from pinning down.

    Update: This can be further simplified to work with just one random bigint. If you want a random number between 0 and n with k decimal precision (where k is a constant), you just generate a random number between 0 and n*10^k and divide it by 10^k.

    0 讨论(0)
  • 2021-01-05 17:43

    I made a post about generating a random BigInteger Andy Turner's answer about generating a random BigInteger. I don't use this directly for generating a random BigDecimal. Essentially my concern is to use independent instances of Random to generate each digit in a number. One problem I noticed is that with Random there are only so many values of and particular number that you get in a row. Also the generation tries to maintain something of an even distribution of generated values. My solution depends on something storing an array or collection of Random instances and calling these. I think this is a good way of going about it and I am trying to find out, so am interested if anyone has any pointers or criticism of this approach.

    /**
     *
     * @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;
    }
    
    0 讨论(0)
  • It's surely very easy... if I only knew what you want. For a uniformly distributed number in range [0, 1) and precision N decimal digits generate a uniform BigInteger less than 10*N and scale it down by 10*N.

    0 讨论(0)
提交回复
热议问题