Java Двойное приращение - PullRequest
0 голосов
/ 23 февраля 2012

У меня есть двойная переменная

public double votes(){
    double votexp = 0;

      for(Elettore e:docenti.values()){
        if(e.getVoto()==true)          //everytime this is true increment by 1
        {
            votexp+=1.0;
        }   
    }
    for(Elettore e:studenti.values()){
        if(e.getVoto()==true)         //everytime this is true increment by 0.2
        {
            votexp+=0.2;
        }
    }
    for(Elettore e:pta.values()){
        if(e.getVoto()==true)        //everytime this is true increment by 0.2
        {
            votexp+=0.2;
        }
    }
    return votexp;
}

В моем случае, переменная должна быть увеличена до 2,6, а voicexp возвращает 2,6000000000000005. Как я могу исправить это, используя ту же двойную переменную и вернуть число с двойной точностью?

Ответы [ 5 ]

6 голосов
/ 23 февраля 2012

Вы накапливаете ошибку округления.Самое простое, что можно сделать, это использовать long (или int и использовать только double в конце. (Или BigDecimal и double в конце, но это слишком сложно)

public double votes() {
    long votexp = 0;
    for (Elettore e : docenti.values())
        if (e.getVoto())          //everytime this is true increment by 1
            votexp += 10;
    for (Elettore e : studenti.values())
        if (e.getVoto())         //everytime this is true increment by 0.2
            votexp += 2;
    for (Elettore e : pta.values())
        if (e.getVoto())        //everytime this is true increment by 0.2
            votexp += 2;
    return votexp / 10.0;
}

double a = 26 / 10.0;
System.out.println(a);

печатает

2.6

Поскольку Double.toString () "знает", что значения могут быть неточными, будет выполнено небольшое количество округлений. Это округление ограничено, поэтому результат работына двух double ошибка может быть слишком большой, чтобы ее можно было скрыть. Если вы правильно округлите свой последний результат, ошибка будет достаточно маленькой и не вызовет проблемы.

2 голосов
/ 23 февраля 2012

Попробуйте использовать класс java.math.BigDecimal.

0 голосов
/ 23 февраля 2012

Вы можете попробовать это

(double)Math.round(value * 10) / 10

но вы никогда не получите хороший результат, если сложите двойные числа, как это

0 голосов
/ 23 февраля 2012

Некоторые числа не могут быть точно представлены в формате с плавающей запятой двойной точности. Похоже, что промежуточное число в ваших вычислениях имеет этот недостаток, который включен в окончательный результат.

0 голосов
/ 23 февраля 2012

Вы должны округлить результат, числа с плавающей точкой в ​​Java (и в основном в любой другой среде) не идеально, и иногда появляются небольшие неточности.

Если вы имеете дело с десятичными числами, есть BigDecimal, которые могут точно представлять то, что вы показали (просто не могут точно представлять другие такие вещи, как 1 / 3).

Кроме того, вы можете умножить на 10, использовать Math.round и поделить на 10, если проблема связана не с фактическим конечным значением, а с неточностями, которые возникли за время, которое вы создали значение. случается в случае с 2.6, построенным так:

double n = 0;

n += 1;
n += 0.2;
n += 1;
n += 0.2;
n += 0.2;

System.out.println("n = " + n);     // "2.6000000000000005"
n = (double)Math.round(n * 10) / 10;
System.out.println("n = " + n);     // "2.6"

... но я не думаю, что есть гарантия, что это обязательно произойдет со всеми значениями. (Я не гуру с плавающей запятой.)

Или , просто беспокойтесь об этом, когда вы выполняете вывод, обрезая результат вывода до соответствующего уровня точности.

...