Skip to content

Latest commit

 

History

History
111 lines (87 loc) · 7.22 KB

README.md

File metadata and controls

111 lines (87 loc) · 7.22 KB

Задача 2. Задача от бухгалтеров

Описание

Следующая задача пришла от наших бухгалтеров. Бухгалтерская программа должна уметь проводить операции c различными агентами, как c физическими/юридическими лицами, так и с иностранными компаниями: чп, ип, ооо, зао, иклмн, ёпрст. С некоторых операций налог платить не нужно, некоторые облагаются подоходным налогом, с некоторых необходимо уплатить НДС. Необходимо расширить функциональность класса Bill возможностью работы с различными системами налогообложения.

Дополнительная информация

Практически в любом языке программирования, если вы напишете нечто подобное, вы получите не то, что вы могли ожидать:

System.out.println(0.1 + 0.2); // => 0.30000000000000004

Связанно это с тем, что числа в компьютере хранятся в двоичном виде, и конечные дроби в десятичной системе счисления 0.1 и 0.2 превращаются в бесконечные периодические дроби в двоичной системе счисления 0.00011001100110011010 и 0.00110011001100110011 соответственно. Как следствие, часть числа теряется, а значит, и точность при операциях с ними. Подробнее про представление вещественных чисел в компьютере на сайте ИТМО.

Для того чтобы производить расчёты с десятичными дробными числами, существует специальный класс BigDecimal (большое десятичное). Большое, потому что у него нет стандартных ограничений как у double (-1.7E+308 до 1.7E+308) или int (-2147483648 до 2147483647). Этот класс может хранить число, состоящее из 2,147,483,647 цифр, Карл! А десятичное, потому что каждая цифра числа хранится по отдельности, из-за чего не возникает проблем с потерями при переводе между системами счисления. В задаче предлагается принять некоторые неточности и использовать уже знакомый нам тип double. Плюсиком будет решение задачи № 2* (со звёздочкой).

Функционал программы

→ Создание нескольких счетов и расчет налогов для них.

Процесс реализации

  1. Класс Bill

В системе уже есть класс Bill, в который мы добавили поле TaxType taxType; и метод payTaxes():

class Bill {
    private double amount;
    private TaxType taxType;
    private TaxService taxService;
    
    public Bill(double amount, TaxType taxType, TaxService taxService) {
        this.amount = amount;
        this.taxType = taxType;
        this.taxService = taxService;
    }
    
    public void payTaxes() {
        // TODO вместо 0.0 посчитать размер налога исходя из TaxType
        double taxAmount = 0.0;
        
        taxService.payOut(taxAmount);
    }
}

А также класс налоговой службы:

class TaxService {
    public void payOut(double taxAmount) {
        System.out.format("Уплачен налог в размере %.2f%n", taxAmount);
    }
}
  1. Создадим классы для различных типов налогообложения.
  • Базовый класс
class TaxType {
    public double calculateTaxFor(double amount) {
        // TODO override me!
        return 0.0;
    }
}
  • Классы, расширяющие TaxType:
    • Подоходный налог, = 13% (IncomeTaxType)
    • НДС, = 18% (VATaxType)
    • Прогрессивный налог, до 100 тысяч = 10%, больше 100 тысяч = 15% (ProgressiveTaxType)
  1. В методе main создадим несколько счетов и оплатим с них налоги в налоговую службу.
public static void main(String[] args) {
    TaxService taxService = new TaxService();
    Bill[] payments = new Bill[] {
        // TODO создать платежи с различным типами налогообложения
    };
    for (int i = 0; i < payments.length; ++i) {
        Bill bill = payments[i];
        bill.payTaxes();
    }
}

Задача 2*

Здесь необходимо реализовать тот же функционал, но используя вместо double –> BigDecimal.

Работа с ним может показаться необычной и странной. Например, их нельзя сложить, используя оператор + (в Java запрещено перегружать операторы), или сравнить с помощью == (так как это объект, произойдёт сравнение ссылок, а не значений объектов). Вместо этого мы должны использовать методы .add(…) и .compareTo(…) соответственно.

Экземпляр этого класса можно создать с помощью new BigDecimal("0.1") или BigDecimal.valueOf(0.2). Как и String, экземпляры этого класса неизменяемые (иммутабельные), а методы .add(…), .multiply(…) возвращают новый объект, содержащий результат операции.

Например, чтобы сложить 0.1 рубля и 0.2 рубля и получить ожидаемые 30 копеек, мы могли бы написать код:

BigDecimal first = new BigDecimal("0.10");
BigDecimal second = BigDecimal.valueOf(0.2);

BigDecimal sum = first.add(second);

System.out.println(sum.toString()); // => 0.30

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