Производительность BigDecimal.valueOf (double d) - PullRequest
2 голосов
/ 27 июля 2011

У меня есть кусок кода, который должен периодически вычислять следующее ...

        double consumption = minConsumption + ( Math.random() * ( ( maxConsumption - minConsumption ) + 1 ) );
        currentReading = currentReading.add( BigDecimal.valueOf( consumption ) ).setScale( 2, RoundingMode.HALF_EVEN ).stripTrailingZeros();

Это используется для генерации случайной информации для тестирования.Казалось, что он работает медленнее, чем я ожидал, и я обнаружил, что медленная часть была BigDecimal.valueOf( consumption ), и это медленно из-за вызова Double.toString(), который происходит внутри.

Общее требование - генерироватьзначение потребления, которое случайно находится между минимумом и максимумом.Затем добавьте это в currentReading, чтобы получить новое чтение.

Можно ли как-нибудь улучшить производительность этого?Возможно, избегая двойного преобразования -> BigDecimal.Мне нужно, чтобы результат был BigDecimal, но я не возражаю против того, как случайный расчет делается до этого.

1 Ответ

7 голосов
/ 27 июля 2011

Вместо того, чтобы вычислять двойное число, которое вы хотите округлить до двух десятичных разрядов, вы можете создать значение типа int, которое сдвигается на два места, т.е. где 1234 представляет 12,34, а затем установить масштаб при создании BigDecimal.т.е. деление его на 100

double min = 100;
double max = 10000000;
{
    long start = 0;
    int runs = 1000000;
    for (int i = -10000; i < runs; i++) {
        if (i == 0)
            start = System.nanoTime();
        double consumption = min + (Math.random() * ((max - min) + 1));

        BigDecimal.valueOf(consumption).setScale(2, BigDecimal.ROUND_HALF_UP);
    }
    long time = System.nanoTime() - start;
    System.out.printf("The average time with BigDecimal.valueOf(double) was %,d%n", time / runs);
}
{
    long start = 0;
    int runs = 1000000;
    int min2 = (int) (min * 100);
    int range = (int) ((max - min) * 100);
    Random rand = new Random();
    for (int i = -10000; i < runs; i++) {
        if (i == 0)
            start = System.nanoTime();
        int rand100 = rand.nextInt(range) + min2;
        BigDecimal bd = BigDecimal.valueOf(rand100, 2);
    }
    long time = System.nanoTime() - start;
    System.out.printf("The average time with BigDecimal.valueOf(long, int) was %,d%n", time / runs);

}

отпечатков

The average time with BigDecimal.valueOf(double) was 557
The average time with BigDecimal.valueOf(long, int) was 18
...