2014-12-30 3 views
0

Это пример кода, который я пытаюсь. Я знаю, что это из-за двойной точности/округления. Но дайте мне знать, что именно происходит и как его преодолеть.Неожиданное поведение двойного типа данных

public class DoubleSample { 

    public static void main(String[] args) { 
     // TODO Auto-generated method stub 
     double price1 = 16.99; 
     double price2 = 12.99; 
     int multiplier =10000; 

     double price1updated = price1 * multiplier; 
     double price2updated = price2 * multiplier; 

     System.out.println("price1 "+price1updated); 
     System.out.println("price2 "+price2updated); 
    } 

} 

Выход

price1 169899.99999999997 
price2 129900.0 
+0

Никто не будет разбираться в математике вручную - прочитайте [this] (http://floating-point-gui.de/) и сделайте это сами. –

ответ

2

Это потому, что double представляет собой десятичное число с поразрядными двумя, а 10 не силы 2. Это означает, что для определенных значений эквивалент double будет отличаться.

Есть два способа решения этой проблемы:

  • Используйте BigDecimal; или
  • Завершить результат до количества цифр «ремонт» двойной себя.

Для решения этой проблемы вы можете использовать BigDecimal. В этом случае код будет читать что-то вроде:

BigDecimal price1 = new BigDecimal("16.99"); 
BigDecimal price2 = new BigDecimal("12.99"); 
BigDecimal multiplier = new BigDecimal(10000); 

BigDecimal price1updated = price1.multiply(multiplier); 
BigDecimal price2updated = price2.multiply(multiplier); 

System.out.println("price1 "+price1updated); 
System.out.println("price2 "+price2updated); 

Или, вы можете округлить ошибки, округляя результаты от до, например, два значащих цифр. Теперь есть небольшой шанс, если вы сделаете это с большими числами, что результат будет неправильным (например, если multiplier больше 1G). В случае, если вы хотите, чтобы закруглить на двух цифр, код гласит:

double price1 = 16.99; 
double price2 = 12.99; 
int multiplier =10000; 

double price1updated = Math.round(price1 * multiplier * 100.0d)*0.01d; 
double price2updated = Math.round(price2 * multiplier * 100.0d)*0.01d; 

System.out.println("price1 "+price1updated); 
System.out.println("price2 "+price2updated); 

Там нет, однако нет гарантии, что это будет всегда помогать и, как уже было сказано, что это возможно результат будет несколько центов больше или меньше (но только на больших количествах, поэтому относительная ошибка очень мала).