/ does integer division for integer operands (should be float per ISO 9.1.4) #17

Closed
opened 2026-05-29 03:25:02 +00:00 by navicore · 1 comment
Owner

Symptom

X is Int1 / Int2 returns an integer (truncated toward zero) instead of the float quotient ISO 13211-1 §9.1.4 requires. Mixed-type and float-only operands behave correctly.

Repro

$ patch-prolog run probe.pl --goal "X is 10 / 3" --format text
X = 3            ← should be 3.3333...

$ patch-prolog run probe.pl --goal "X is 10.0 / 3" --format text
X = 3.3333333333333335   ← correct (float operand)

$ patch-prolog run probe.pl --goal "X is -10 / 3" --format text
X = -3           ← should be -3.3333...

$ patch-prolog run probe.pl --goal "X is 10 // 3" --format text
X = 3            ← correct: // is integer division

Root cause

crates/patch-prolog-core/src/builtins.rs:706 (arith_div) — the Int/Int arm calls i64::checked_div and wraps the result in ArithVal::Int. That's what // should do; / should evaluate to a float per ISO. The other arms (Float/Float, Int/Float, Float/Int) all go through check_float, so they already produce float results correctly.

Impact

Subtle for casual use, sharp for anything that mixes Prolog with code that expects ISO-conforming arithmetic. Teaching it correctly in the loglings curriculum requires steering students to // for the "integer dozens" exercise instead of letting them use / — which is awkward because / is the universal "divide" symbol everywhere else.

It also produces silently wrong answers — no error, no warning, just the wrong number. That's the worst kind of language gap.

Suggested fix

In arith_div, change the Int/Int arm to compute (*a as f64) / (*b as f64) and feed it through check_float(...). The zero-divisor guard above it stays. // (arith_int_div around line 738) is already a separate function and is unaffected.

Update the divide-by-zero error label for / from "integer division" to "float division" since the operation is now float-valued (or just drop the qualifier; 1 / 0 would otherwise inherit a misleading label).

Add a unit test in arith_div's test cluster covering: 10 / 3 = 3.333..., -10 / 3 = -3.333..., 1 / 0 throws evaluation_error(zero_divisor).

ISO reference

ISO 13211-1 §9.1.4 — the (/)/2 evaluable functor. The Number Result table specifies float result for both integer and float operands.

## Symptom `X is Int1 / Int2` returns an integer (truncated toward zero) instead of the float quotient ISO 13211-1 §9.1.4 requires. Mixed-type and float-only operands behave correctly. ## Repro ``` $ patch-prolog run probe.pl --goal "X is 10 / 3" --format text X = 3 ← should be 3.3333... $ patch-prolog run probe.pl --goal "X is 10.0 / 3" --format text X = 3.3333333333333335 ← correct (float operand) $ patch-prolog run probe.pl --goal "X is -10 / 3" --format text X = -3 ← should be -3.3333... $ patch-prolog run probe.pl --goal "X is 10 // 3" --format text X = 3 ← correct: // is integer division ``` ## Root cause `crates/patch-prolog-core/src/builtins.rs:706` (`arith_div`) — the Int/Int arm calls `i64::checked_div` and wraps the result in `ArithVal::Int`. That's what `//` should do; `/` should evaluate to a float per ISO. The other arms (`Float/Float`, `Int/Float`, `Float/Int`) all go through `check_float`, so they already produce float results correctly. ## Impact Subtle for casual use, sharp for anything that mixes Prolog with code that expects ISO-conforming arithmetic. Teaching it correctly in the loglings curriculum requires steering students to `//` for the "integer dozens" exercise instead of letting them use `/` — which is awkward because `/` is the universal "divide" symbol everywhere else. It also produces *silently* wrong answers — no error, no warning, just the wrong number. That's the worst kind of language gap. ## Suggested fix In `arith_div`, change the Int/Int arm to compute `(*a as f64) / (*b as f64)` and feed it through `check_float(...)`. The zero-divisor guard above it stays. `//` (`arith_int_div` around line 738) is already a separate function and is unaffected. Update the divide-by-zero error label for `/` from "integer division" to "float division" since the operation is now float-valued (or just drop the qualifier; `1 / 0` would otherwise inherit a misleading label). Add a unit test in `arith_div`'s test cluster covering: `10 / 3 = 3.333...`, `-10 / 3 = -3.333...`, `1 / 0` throws `evaluation_error(zero_divisor)`. ## ISO reference ISO 13211-1 §9.1.4 — the `(/)/2` evaluable functor. The Number Result table specifies float result for both integer and float operands.
Author
Owner

#22

https://git.navicore.tech/navicore/patch-prolog/pulls/22
Sign in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
navicore/patch-prolog#17
No description provided.