Рассмотрим решение с использованием алгебраических c типов данных для определения скобок и PositiveInfinity
для имитации открытого интервала
abstract class TaxBracket(val from: Double, val to: Double, val rate: Double) {
def tax(income: Double) = {
if (income >= from)
if (to.isPosInfinity) (income - from) * rate
else if (income - to > 0) (to - from) * rate
else (income - (from - 1)) * rate
else
0.0
}
}
case object A extends TaxBracket(0, 12500, 0.0)
case object B extends TaxBracket(12501, 50000, 0.2)
case object C extends TaxBracket(50001, 150000, 0.4)
case object D extends TaxBracket(150001, Double.PositiveInfinity, 0.45)
Теперь расчет налога упрощается до
def tax(income: Double, bands: List[TaxBracket]): Double =
bands.map(_.tax(income)).sum
, например, с использованием Налоговые полосы Великобритании , определенные выше, мы получаем
tax(60000, List(A, B, C, D)) // res0: Double = 11499.8
, который можно проверить здесь .
Чтобы получить минимальный доход для данной эффективной ставки налога попробуйте
def income(etr: Double, bands: List[TaxBracket]): Option[Double] = {
bands.map(b => (b.from, b.to)).find { case (from, to) =>
if (to.isPosInfinity) true
else (tax(to, bands) / to) >= etr
}.map { case (lowerBound, upperBound) => lowerBound }
}
income(0.4, List(A, B, C, D)) // res1: Option[Double] = Some(150001.0)