Books / Law as Code in Practice: German Housing Benefit (Wohngeld) / Chapter 4

Part II · Chapter 4

The § 19 Formula: Anlagen 2 and 3 and One Rounding

7 min read

Full-page risograph illustration: two blank sheets side by side, a thin red line stepping up between them at a small golden square.
Contents of Law as Code in Practice: German Housing Benefit (Wohngeld)

By the end of this chapter you will be able to compute the Vogts’ €485 by hand, step by step, and say where the Act fixes the arithmetic and where the model had to choose.

Lawyer: which provision fixes the order of the steps and the rounding.
Analyst: how sensitive the amount is to M and Y.
Developer: which four nodes of the proof carry the formula, and how z1 to z3 are recomputed from them.

1. The question

You know the three inputs from Chapter 2: four household members, M = €777.80, Y = €1,710.00. How do they become €485?

Predict before you read on: in how many places does the Act let the calculation round — everywhere, once at the end, or nowhere?

2. The formula as the Act writes it

§ 19 Abs. 1 WoGG:

Das ungerundete monatliche Wohngeld für bis zu zwölf zu berücksichtigende Haushaltsmitglieder beträgt 1,15 · (M – (a + b · M + c · Y) · Y) Euro. „M“ ist die zu berücksichtigende monatliche Miete oder Belastung in Euro. „Y“ ist das monatliche Gesamteinkommen in Euro. „a“, „b“ und „c“ sind nach der Anzahl der zu berücksichtigenden Haushaltsmitglieder unterschiedene Werte und ergeben sich aus der Anlage 2.

In English: the unrounded monthly Wohngeld for up to twelve counted members is 1.15 · (M − (a + b · M + c · Y) · Y) euros, with a, b and c taken from Anlage 2 by the number of members.

§ 19 Abs. 2 adds that the steps and roundings must be carried out in the order set out in Anlage 3. Anlage 3 is short and exact:

  1. values of M and Y below the minimums in its table are replaced by those minimums;
  2. the formula is computed in four intermediate steps, z1 to z4, “als Festkommazahlen mit zehn Nachkommastellen” — as fixed-point numbers with ten decimal places;
  3. the result is rounded to the full euro: below 50 cents down, from 50 cents up.

So the answer to the prediction: there is one rounding to the full euro, at the end. The intermediate results are held at ten decimal places; how a longer intermediate result is brought to ten places is the model’s choice, explained in section 5.

3. The Vogts, step by step

For four members, the second WoGFV sets a = 0.01, b = 2.163 × 10⁻⁴ and c = 1.760 × 10⁻⁵, and the minimums M = €92 and Y = €1,132. The Vogts are above both minimums, so step 1 changes nothing.

Step Calculation Value
z1 a + b · M + c · Y = 0.01 + 0.0002163 · 777.80 + 0.0000176 · 1,710 0.2083341400
z2 z1 · Y 356.2513794000
z3 M − z2 421.5486206000
z4 1.15 · z3 484.7809136900
rounding 484.78… to the full euro €485

The proof of the model’s answer contains the same z4 — 484.78091369, trailing zeros dropped — on the node of the rule WohngeldUngerundet, and the rounded €485 on the node WohngeldGerundetBisZwoelf. On 31 December 2024, with the values of the Wohngeld-Plus-Gesetz (b = 2.251 × 10⁻⁴, c = 2.000 × 10⁻⁵), the same steps give z4 = 463.2504131300 and €463.

Read the table backwards and you see the logic of the benefit: z2 is the part of the rent the household is expected to carry itself, growing with income; Wohngeld pays 115 % of the rest.

4. The steps in the model

The model writes the three numbers of Anlage 3 as rules: Nr. 1, the minimums of M and Y, as two rules; Nr. 2 as one rule whose function computes z1, z2 and z3 as intermediate values and records z4; and Nr. 3, the rounding to the euro, as a rule of its own. The proof therefore shows four nodes for the formula — M, Y, z4 and the rounded amount — and z1 to z3 are recomputed from them, as in the table above:

function z4_berechnen(k: Integer, m: Decimal, y: Decimal) -> Decimal {
    let z1: Decimal = round(wert_a(k) + wert_b(k) * m + wert_c(k) * y, 10, "HALF_UP");
    let z2: Decimal = round(z1 * y, 10, "HALF_UP");
    let z3: Decimal = m - z2;
    return round(FormelFaktor * z3, 10, "HALF_UP");
}

rule WohngeldGerundetBisZwoelf(h: Haushalt, z4: Decimal, n: Integer) strict {
    label de official "Anlage 3 Nummer 3: bis unter 0,50 Euro auf den nächsten vollen Euro-Betrag abzurunden, von 0,50 Euro an aufzurunden";
    when wohngeld_ungerundet(h, z4) and anzahl_zu_beruecksichtigende_haushaltsmitglieder(h, n) and n <= 12;
    then wohngeld_monatlich(h, 1.00 EUR * round(z4, 0, "HALF_UP"));
}

Three things to notice:

  • The arithmetic is exact. No binary floating point: decimals stay decimals, and each intermediate value is held at exactly the ten places the Anlage asks for.
  • The rounding to the euro is where the Act puts it — one rule, labelled with the words of Anlage 3 Nr. 3, after z4 and nowhere else.
  • a, b and c are parameters, not constants in the code. wert_b(k) reads the row of Anlage 2 in force on the date of the question; that is how the same function gives €463 and €485 in Chapter 1.

5. The one choice the text leaves open

Anlage 3 says “mit zehn Nachkommastellen zu berechnen” — compute with ten decimal places. It does not say how a longer intermediate result is brought to ten places: rounded or cut off. For the products in z1 and z2 this can matter in the last place.

The model takes commercial rounding (half up) — the method Anlage 3 Nr. 3 prescribes for the final step, and § 43 Abs. 4 and 7–9 for the amounts in euros of each update. The Act is not uniform, though: for the values b and c, § 43 Abs. 5 and 6 order them to be rounded down at the seventh decimal place. So the text gives no single answer for the intermediate values z1 to z4; the model chooses half up and documents the choice beside the function. When does it matter? Different methods for the intermediate steps can move the final euro only when z4 lies very close to a half euro. For the Vogts, z4 = 484.78…, far from 484.50; both methods give €485. A reader who prefers the other method can see exactly which line to change and which cases it could affect.

6. Change one thing

How strongly do M and Y move the amount? Two variations of the Vogts’ case, run through the model (Chapter 3 shows them in full):

  • Higher rent. At a rent of €850, M rises by €220.40 to the ceiling’s €998.20, and the Wohngeld from €485 to €644 — about 72 cents per euro of M.
  • Lower income. If income tax were also expected, § 16 would deduct a third 10 %; Y falls by €213.75 to €1,496.25, and the Wohngeld rises to €542 — about 27 cents per euro of Y.

The formula is built that way: in the Vogts’ range, each euro of rent taken into account raises the benefit far more than each euro of income lowers it. Neither variation needs a new formula — only a new fact.

7. What this gives the authority

When a household asks “why €485 and not €490?”, the caseworker can show M, Y and z4 from the proof with the values of the right Anlage, recompute z1 to z3 from them, and point to the one rounding the Act allows. When the ministry publishes a worked example, the office can compare it step by step, not only at the last line. And where the model made a choice the text does not make, the choice is written down where a reviewer will find it.

8. Where Catala stands on this

Catala supports exact rational decimals and gives decimal-to-money conversion a defined rounding to the nearest cent (Catala book, ch. 5.2). That is a clear computational convention, and for a formula like § 19 it gives exact intermediate values too. Arxo adds that each of the three numbers of Anlage 3 is a rule, tied to the rows of the Anlagen it read: M, Y, z4 and the single euro rounding can be checked in the answer itself, and z1 to z3 recomputed by hand from M and Y.

9. Run it

law ask <case package> --case Familie2025 --query-json queries/wohngeld-485.json --out runs/familie-2025

In runs/familie-2025/result.json, find the proof node whose rule is WohngeldUngerundet. Its conclusion carries z4. Its attribute a3Selections names the rows of Anlage 2 it read, and the factor 1.15:

WertAMitglieder4#2025-01-01
WertBMitglieder4#2025-01-01
WertCMitglieder4#2025-01-01
FormelFaktor#2023-01-01

Recorded on 12 October 2026 with law 0.1.12.

Exercise

  1. Using the values of section 3, compute z1 for 31 December 2024 (a = 0.01, b = 2.251 × 10⁻⁴, c = 2.000 × 10⁻⁵, M = 777.80, Y = 1,710).
  2. A colleague rounds z1 and z2 to the cent “to keep it simple”. Why does the model not do that?
  3. In which single situation could the model’s reading of “zehn Nachkommastellen” and the alternative reading give different amounts?

Contents · PDF · EPUB · Free under CC BY 4.0

Law as Code in Practice: German Housing Benefit (Wohngeld)

Contents

You’re reading · Part II

How the Model Is Built

Reading settings

Text size
Appearance

Preferences and your reading place are saved only in this browser.