Что делать, если результат вычислений double дает лишнюю дробную часть?

Рейтинг: 0Ответов: 2Опубликовано: 16.03.2023

Что делать, если результат вычислений double дает лишнюю дробную часть? Скажем должно получится число 2, а получается 1.999999996.

public class ComplexNumberTest{
    public static void main(String[] args) {
        ComplexNumber cn1 = new ComplexNumber(-5.1, 8.3);
        ComplexNumber cn2 = new ComplexNumber(-3.1, 4.8);
        System.out.println(cn1.sum(cn2));
        System.out.println(cn1.subtraction(cn2));
        System.out.println(cn1.multiplication(cn2));
        System.out.println(cn1.module());
    }
}

class ComplexNumber{
    private double realPart;
    private double imaginaryPart;
    
    
    public ComplexNumber(){}
    
    public ComplexNumber(double r){
        this.realPart = r;
    }
    
    public ComplexNumber(double r, double i){
        this.realPart = r;
        this.imaginaryPart = i;
    }
    
    public double getRealPart(){
        return this.realPart;
    }
    
    public void setRealPart(double r){
        this.realPart = r;
    }
    
    public double getImaginaryPart(){
        return this.imaginaryPart;
    }
    
    public void setImaginaryPart(double i){
        this.imaginaryPart = i;
    }
    
    public ComplexNumber sum(ComplexNumber that){
        ComplexNumber result = new ComplexNumber();
        result.setRealPart(this.getRealPart() + that.getRealPart());
        result.setImaginaryPart(this.getImaginaryPart() + that.getImaginaryPart());
        return result;
    }
    
    public ComplexNumber subtraction(ComplexNumber that){
        ComplexNumber result = new ComplexNumber();
        result.setRealPart(this.getRealPart() - that.getRealPart());
        result.setImaginaryPart(this.getImaginaryPart() - that.getImaginaryPart());
        return result;
    }
    
    public ComplexNumber multiplication(ComplexNumber that){
        ComplexNumber result = new ComplexNumber();
        result.setRealPart((this.getRealPart() * that.getRealPart()) - (this.getImaginaryPart() * that.getImaginaryPart()));
        result.setImaginaryPart((this.getRealPart() * that.getImaginaryPart()) + (that.getRealPart() * this.getImaginaryPart()));
        return result;
    }
    
    public Double module(){
        Double result = new Double(0);
        result = Math.sqrt((this.getRealPart() * this.getRealPart()) + (this.getImaginaryPart() * this.getImaginaryPart()));
       
       // Double tmp = this.getRealPart() > 0 ? this.getRealPart() : -this.getRealPart();
       // result.setRealPart(tmp);
        return result;
    }
    
    @Override
    public String toString(){
        return "{ " + this.getRealPart() + ", " + this.getImaginaryPart() + "}";
    }
}

Ответы

▲ 3

В ответе на вопрос описано почему именно такое поведение при операциях над числами с плавующей точкой, к коим относятся и double, как в вашем вопросе, и float.

Именно из-за такого особенностей операций с плавующей точкой нижеописанный код выведет 0.30000000000000004.

double a = 0.1;
double b = 0.2;
System.out.println(a + b);
// Выведет: 0.30000000000000004

Что можно с этим сделать?

Вы можете заменить использование double на BigDecimal. Класс BigDecimal специально предназначен для представления десятичных дробей и для точных операций с ними.

Код ниже с использованием BigDecimal уже выведет ожидаемые 0.3.

BigDecimal aBd = new BigDecimal("0.1");
BigDecimal bBd = new BigDecimal("0.2");
System.out.println(aBd.add(bBd));
// Выведет: 0.3
▲ 2

Что делать, если результат вычислений double дает лишнюю дробную часть? Скажем должно получится число 2, а получается 1.999999996.

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

А вообще этот вопрос уже задавался и на него есть отличные ответы - Вычисления на числах с плавающей точкой работают неправильно