2013-07-24 2 views
2
public class TestMain { 

    public static void main(String[] args) { 
     Double value = 1.25 * ((19.6/100) + 1); 
     System.out.println(value); 
     Double value2 = (1.25 * (19.6/100)) + (1 * 1.25); 
     System.out.println(value2); 
    } 
} 

, результат которого является:Различные результаты между Expended и разложенного расчетом

1.4949999999999999 
1.495 

, и я не понимаю, почему они разные ...

Я добавил явно скобки, чтобы проверить различные случаи, и я не понимаю, почему форму Factored возвращают 1.49499 и форму developed возвращают то, что я хочу: 1.495.

+0

Арифметика с плавающей точкой не является точной. Это не полностью соответствует действительным арифметическим правилам. – johnchen902

+3

[Что каждый компьютерный ученый должен знать о арифметике с плавающей точкой] (http://docs.oracle.com/cd/E19957-01/806-3568/ncg_goldberg.html) и [что каждый программист должен знать о плавающей точке Арифметика] (http://floating-point-gui.de/) –

ответ

1

Поскольку некоторые числа с плавающей запятой не могут быть представлены конечным числом битов без округления. Floating-point numbers имеют ограниченное количество цифр, они не могут точно представлять все real numbers: когда число больше, чем позволяет формат, оставшиеся объекты опущены - число округлено.

Возможно, вы должны прочитать What Every Computer Scientist Should Know About Floating-Point Arithmetic и this answer.

Я не понимаю, почему факторинговая форма возвращает 1.49499, а развернутая форма возвращает то, что я хочу: 1.495.

Я не уверен точно, но, похоже, в первом случае прерывные результаты были округлены.

2

Если вам нужны точные результаты с помощью плавающих точек, вы можете использовать класс BigDecimal.

BigDecimal factor = new BigDecimal(19.6); 
BigDecimal multiplier = new BigDecimal(1.25); 
BigDecimal oneHundred = new BigDecimal(100); 
BigDecimal one = new BigDecimal(1); 

BigDecimal res = multiplier.multiply(factor.divide(oneHundred).add(one)); 
System.out.println(res); 

BigDecimal res2 = multiplier.multiply(factor.divide(oneHundred)).add(one.multiply(multiplier)); 
System.out.println(res2); 

приводит:

1.495000000000000017763568394002504646778106689453125 
1.495000000000000017763568394002504646778106689453125 
+1

Вы должны использовать конструктор 'BigDecimal (String)'. –

+0

@Rohit Jain: не могли бы вы объяснить, почему? Есть ли разница между BigDecimal (1) и BigDecimal («1»)? – kaos

1

BASIC CONCEPT
1. когда мы делаем addition из двух decimal числа он никогда extends десятичной точки.
2. когда мы делаем multiplication из двух decimal номер будет extends его десятичной точкой, если требуется.

Чтобы понять концепцию Java Code

public static void main(String[] args) { 
     Double v1 = (19.6/100); 
     System.out.println("inti v1 = "+v1); 
     v1 += 1; 
     System.out.println("1 + v1 = "+v1); 
     v1 *= 1.25; 
     System.out.println("Ans = 1.25 * v1 = "+v1); 
     Double v2 = (19.6/100); 
     Double v3 = (double) 1; 
     System.out.println(" inti v2 = "+v2); 
     System.out.println("inti v3 = "+v3); 
     v2 *= 1.25; 
     v3 *= 1.25; 
     System.out.println("1.25 * v2 = "+v2); 
     System.out.println("1.25 * v3 = "+v3); 
     Double v4 = v2+v3; 
     System.out.println("Ans v2 + v3 = v4 = "+v4); 
    }} 

Выходной

1. inti v1 = 0.196 
2. 1 + v1 = 1.196 
3. Ans = 1.25 * v1 = 1.4949999999999999 

4. inti v2 = 0.196 
5. inti v3 = 1.0 
6. 1.25 * v2 = 0.245 
7. 1.25 * v3 = 1.25 
8. Ans v2 + v3 = v4 = 1.495 

приборную номер строки в выходной, чтобы легко понять концепцию.

Это не совсем другая программа, но один за другим процесс, следующий за математикой для +/*, в вашем коде.

Вы можете увидеть на выходе,
Line 3, Line 6, Line 7 там мы умножали там extended его десятичной точки.
и в Line 2 & Line 8 мы делаем addition, как вы знаете addition никогда не расширяйте свою десятичную точку, чтобы отобразить наибольшую десятичную точку.

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