仅适用于小于 5000 个 args 参数的方法

Method working only with < than 5000 args parameters

我在将 "n.n+, n.n+, n.n+, ..., n.n+ ." 之类的字符串转换为双精度序列的方法时遇到了一个小问题。 如果我的值少于 4998,一切都很好。如果我有 4998 或更多,则抛出以下异常:

Exception in thread "main" java.lang.NumberFormatException: For input string: "1.178293466734042,"
        at java.base/jdk.internal.math.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:2054)
        at java.base/jdk.internal.math.FloatingDecimal.parseDouble(FloatingDecimal.java:110)
        at java.base/java.lang.Double.parseDouble(Double.java:543)
        at java.base/java.lang.Double.valueOf(Double.java:506)

这是我写的方法:

private static void parseDoubleArrayFromInput (String[] input, double[] parsedDoubles){
        for(int i = 0 ; i < input.length - 1; i++){                     //Removes the last character, which is the comma, apart from the last valid string.
            if(i == input.length - 2)                                   //Does not consider the last string of the array since it contains only the dot.
                parsedDoubles[i] = Double.parseDouble(input[i]);        //Then, it fills the array of doubles with the parsed double.
            else
                parsedDoubles[i] = Double.parseDouble(input[i].substring(0,input[i].length()-1));
        }
    }

这是生成文件的class

import java.time.*;

public class PRNG {

    public PRNG(){

    }

    public static String generatePseudoRandomNumbers(double actual, int repetitions) {        //main function, generates pseudo random numbers and
        String output = "";
        double[] values = new double[repetitions];
        for(int i = 0; i < repetitions; i++) {
            double nextNumber = Math.pow(7,5)* actual % (Math.pow(2,31)- 1);    //algorithm to generate next pseudo random number
            actual = nextNumber;
            double singleResult = (2*(actual / (Math.pow(2,31) - 2))); //equation to shrink random numbers in a little range (0..100 in this case)
            output = output + singleResult + ", ";
        }
        output = output.substring(0, output.length()-3) + " .";
        return output;
    }

    public static int generatePseudoRandomNumbersTimes(double actual) {
        double nextNumber = Math.pow(7,5)* actual % (Math.pow(2,31)- 1);
        int singleResult = (int)(21*(nextNumber / (Math.pow(2,31) - 2)));
        return singleResult;
    }
}

这是 class 应该接收输入并按双精度序列解析它

import java.util.Arrays;

public class StupidAlg {

    public static void main (String[] args){
        double[] doubleInput;
        if (args.length ==0) {
            System.out.print("");
        }
        else {
            doubleInput = new double[args.length - 1];
            parseDoubleArrayFromInput(args, doubleInput);
            double target = sum(doubleInput) / 2;                   //find target value
            double value = findWeightedMedian(doubleInput, target);
            System.out.print(value);
        }
    }

    private static void parseDoubleArrayFromInput (String[] input, double[] parsedDoubles){
        // process all of the input
        for(int i = 0 ; i < input.length - 1; i++) {
            // remove from the input things that will break the parsing
            // NOTE: other approaches could be used to ensure there is
            //   only a single ".".
            // NOTE: assumes the input to be US standard, as other approachs
            //        might use a "," for separator
            String clean = input[i].replaceAll("[^0-9.]", "");

            // put the result
            parsedDoubles[i] = Double.parseDouble(clean);
        }
    }

    private static double findWeightedMedian (double[] input, double target){
        Arrays.sort(input);
        double sum = 0;
        double result = 0;
        for(double v : input){
            sum += v;
            if (sum >= target) {
                result = v;
                break;
            }
        }
        return result;
    }

    private static double sum (double[] input){
        double result = 0;
        for(double v : input){
            result = result + v;     //sum all values in array
        }
        return result;
    }
}

我使用库 Arrays 只是因为我不想实现排序算法,因为这是一个简单的问题,这是测试文件。

输入文件是这样制作的

0.2931308777007562, 0.650659222761783, 1.6295518657467811, 1.8781948535500046, 0.8208889158637159, 0.680002497211101, 0.8019653053972547, 0.6308815354768946, 1.2259618232268485, 0.7403533791567696, 1.1192376940690332, 1.0279154591522324, 0.1751139268047306, 1.139766437131694, 0.05449995217332612, 1.9806957514776808, 1.5534795844494176, 1.3313636838750575, 0.22942446845530018, 1.937039533571377, 1.8234255749950423, 0.31362467102112684, 1.08984339804374, 0.9979823920856997, 1.090055974284239, 0.570751264291583 .

异常非常明显——如果输入字符串不是预期的格式。

所以,最好是:

  • 捕获异常,或者知道它可以传播
  • 在尝试解析之前检查输入的有效性

当前算法假定错误值的位置。这种方法看起来非常脆弱。我会清理输入,并允许异常传播。

private static void parseDoubleArrayFromInput (String[] input, double[] parsedDoubles){
    // process all of the input
    for(int i = 0 ; i < input.length; i++) {
        // remove from the input things that will break the parsing
        // NOTE: other approaches could be used to ensure there is 
        //   only a single ".".
        // NOTE: assumes the input to be US standard, as other approachs
        //        might use a "," for separator
        String clean = input[i].replaceAll("[^0-9.]", "");

        // put the result
        parsedDoubles[i] = Double.parseDouble(clean);
    }
}   

通常 Array 在内部使用 int,因此应该允许 Integer.MAX_VALUE 但它还取决于您存储到 Array 中的数据类型及其大小以及可用于堆的内存大小。可能不是您正在寻找的答案,但值得一试。你可以找到详细信息 here