2013-08-14 3 views
2

Я нашел ошибку округления с моим Java-приложением. Метод, используемый для тура был:Ошибка округления Java

public static double round(double value,double precision) 
    { 
     return Math.round(value * precision)/precision; 
    } 

Это может иметь ошибку (т.е. раунд (138.515,100) должен возвращать 138.52, и возвращает 138.51) Таким образом, я создал следующий круглее:

// Mikeldi's rounder 
public static double round2DecimalPlaces(double value,int decimalPlaces) 
{ 
    int s = value<0?-1:1; 
    double p = 1; 
    for (int i = 0; i < decimalPlaces; i++) { 
     p*=10; 
    } 

    double n = (long) value; 
    double d = ((value*10*p)-(n*10*p)); 
    d +=s*5; 
    d /= 10; 
    d = (long)d; 
    d /= p; 
    return d+n; 
} 

Я создал этот метод, поскольку другие методы округления добавили слишком много латентности в систему (система с низкой задержкой). Это примерно в 10 раз быстрее предыдущего.

Примечание: этот кругмер будет использоваться только для округления до способного decimalPlaces (или 0).

Есть ли какие-либо проблемы, которые я не видел с этим новым товаром?

Спасибо,

+0

«Есть ли какие-либо проблемы, которые я не видел с этим новым кружком?» Это зависит от того, что вы хотите достичь ... Исправлено из всего, что вы должны написать какой-то единичный тест, который будет сравнивать ваш вывод метода с доверенным методом, который вы хотите сделать работу быстрее. И затем загляните во все, что не соответствует, и подумайте, приемлемы ли эти различия, если они существуют, или нет. – dantuch

ответ

11

Метод Math#round не сломаны. 138.515 не может быть точно представлен как двойной. Чтобы увидеть точное значение, вы можете использовать:

System.out.println(new BigDecimal(138.515d)); 

который печатает:

138.5149999999999863575794734060764312744140625 

Поэтому точный для круглых вернуться 138.51. Если вам нужна более высокая точность, чем может дать double, вы можете использовать BigDecimal.


EDIT

Если BigDecimal не вариант, а если количество десятичных знаков низковат (скажем, 3 или 4, потому что эти цены, например), вы можете использовать длинные позиции вместо с последними 4 цифрами будучи десятичным. Таким образом, 138.51d вместо этого будет 1385100L.

+0

Это добавляет слишком много регенерации в систему. – magodiez

+0

@magodiez see my edit – assylias

+0

Цифры на самом деле являются ценами, но в разных случаях нужно применять разные требования. Appart от этого, мы используем внешний алгоритм оптимизации, который должен использовать цены как двойные. – magodiez

Смежные вопросы