# Rounding required by the rule ## Intention I want to set the scale and rounding mode of a money amount explicitly. The policy must be explicit: the scenes below check the positive and negative half-steps and the HALF_UP/HALF_EVEN difference. ## Incorrect form and why it stays silent ```text title="Incorrect form" pure function Pay(x: Money) -> Money = round(x); ``` Rounding has no hidden scale or mode. Trailing zeros on a literal do not set legal precision: the arguments of round do. ## Correct form ```law language "law.core" version "0.2"; package recipes.l.r03 version "0.1.0"; namespace "urn:recipe:l-calc:03"; pure function Pay(x: Money) -> Money = round(x, 2, "HALF_UP"); ``` ## Frozen execution scene | Facts and choice | Question | Answer | |---|---|---| | 1. positive half-step | `Pay(1.005 KZT)` | `1.01 KZT` / `COMPUTED` | | 2. negative half-step | `Pay(-1.005 KZT)` | `-1.01 KZT` / `COMPUTED` | | 3. banker's rounding of a half | `round(1.005 KZT, 2, "HALF_EVEN")` | `1 KZT` / `COMPUTED` | | 4. literal zeros do not change the amount | `Pay(1.5000 KZT)` | `1.5 KZT` / `COMPUTED` | ```law test "positive half step up" { given { context { legal_time @2026-09-13; decision_time @2026-09-13T09:00:00+05:00; knowledge_time @2026-09-13T09:00:00+05:00; timezone "Asia/Almaty"; } } evaluate Pay(1.005 KZT); expect value == 1.01 KZT; expect evaluation_status == COMPUTED; } ``` ```law test "negative half step" { given { context { legal_time @2026-09-13; decision_time @2026-09-13T09:00:00+05:00; knowledge_time @2026-09-13T09:00:00+05:00; timezone "Asia/Almaty"; } } evaluate Pay(-1.005 KZT); expect value == -1.01 KZT; expect evaluation_status == COMPUTED; } ``` ```law test "banker's rounding of half" { given { context { legal_time @2026-09-13; decision_time @2026-09-13T09:00:00+05:00; knowledge_time @2026-09-13T09:00:00+05:00; timezone "Asia/Almaty"; } } evaluate round(1.005 KZT, 2, "HALF_EVEN"); expect value == 1 KZT; expect evaluation_status == COMPUTED; } ``` ```law test "literal zeros keep sum" { given { context { legal_time @2026-09-13; decision_time @2026-09-13T09:00:00+05:00; knowledge_time @2026-09-13T09:00:00+05:00; timezone "Asia/Almaty"; } } evaluate Pay(1.5000 KZT); expect value == 1.5 KZT; expect evaluation_status == COMPUTED; } ``` ## Counterfactual Mutation: `round(x, 2, "HALF_UP")` → `round(x)`; expected `LDC-E2116`. Additional counterfactuals are shown as separate table rows. ## Boundary Round at the stage the rule names. For a quotient, first compute it exactly or use div_round — see [Division under an explicit policy](/recipes/l-calc/division-precision/). Canonical value notation may drop trailing zeros; that is not a change of rounding mode. ## Pitfall Rounding with an unstated scale or mode has no default; the scenes pin both half-steps and both modes.