Write exact results past the range of a double (closes #16) #18

Merged
clawbot merged 3 commits from issue-16-exact-results-past-float64 into next 2026-09-29 09:56:56 +02:00
Collaborator

For #16.

What changed

  • format wrote every result through float64 and refused one outside a double's normal range, exact results included. Such a result is now written from its exact value in exponent form, rounded to 17 significant digits, the most a double's shortest form takes, with trailing zeros dropped. Results inside the range are written as before.
  • A fractional power turned its base into a double first and refused one outside that range. Such a base is now brought into it by square roots taken from its exact value, the exponent doubled for each, so (2^1200)^0.5 is 4.149515568880993e+180; only a result that is not a normal double is refused. The other power paths already held these results exactly. A number past the 4096-bit limit (2^4095, 10^1233) is still refused.
  • The README's Arithmetic bullet and docs/TODO.md are updated; the bot test's out-of-range example is now 1e1300, as 1e400 is answered.

Worth knowing

  • 2^1200 is 1.7218479456385751e+361; the issue comment's 1.7218479456305e+361 only showed the style.
  • The rounding goes through a big.Float of 4096 + 64 bits: at the precision SetRat picks by default, a tiny result a hair off halfway between two 17-digit numbers can round the wrong way.
  • This undoes the judgement call on #11 that refused exact results below about 2.2e-308: 1e-310 is answered again.

Judgement call: a power computed in float64 and taken past the range by exact arithmetic is written like any exact result, carrying its float64 rounding (2^0.5 * 1e400 is 1.4142135623730951e+400).

Model: opus-5-5

For https://git.eeqj.de/sneak/simplexcalc/issues/16. **What changed** - `format` wrote every result through float64 and refused one outside a double's normal range, exact results included. Such a result is now written from its exact value in exponent form, rounded to 17 significant digits, the most a double's shortest form takes, with trailing zeros dropped. Results inside the range are written as before. - A fractional power turned its base into a double first and refused one outside that range. Such a base is now brought into it by square roots taken from its exact value, the exponent doubled for each, so `(2^1200)^0.5` is `4.149515568880993e+180`; only a result that is not a normal double is refused. The other power paths already held these results exactly. A number past the 4096-bit limit (`2^4095`, `10^1233`) is still refused. - The README's Arithmetic bullet and `docs/TODO.md` are updated; the bot test's out-of-range example is now `1e1300`, as `1e400` is answered. **Worth knowing** - `2^1200` is `1.7218479456385751e+361`; the issue comment's `1.7218479456305e+361` only showed the style. - The rounding goes through a `big.Float` of 4096 + 64 bits: at the precision `SetRat` picks by default, a tiny result a hair off halfway between two 17-digit numbers can round the wrong way. - This undoes the judgement call on https://git.eeqj.de/sneak/simplexcalc/pulls/11 that refused exact results below about 2.2e-308: `1e-310` is answered again. Judgement call: a power computed in float64 and taken past the range by exact arithmetic is written like any exact result, carrying its float64 rounding (`2^0.5 * 1e400` is `1.4142135623730951e+400`). Model: opus-5-5
clawbot added the needs-review label 2026-09-29 08:29:46 +02:00
clawbot self-assigned this 2026-09-29 08:29:46 +02:00
clawbot added 1 commit 2026-09-29 08:29:47 +02:00
An exact result outside the normal range of a double, such as 2^1200,
10^400 or 2^-1200, was refused because format wrote every result
through float64. Such a result is now written from its exact value,
rounded to 17 significant digits with trailing zeros dropped, through a
big.Float precise enough to round as the exact value would. Results
inside the range are written as before, and a power computed in float64
must still be a normal double. The tests check the written text of these
results, the refusals just past the 4096-bit limit, and the time taken
to write the largest and smallest numbers under it.

Model: opus-5-5
clawbot added 1 commit 2026-09-29 08:41:33 +02:00
Merge next into issue-16-exact-results-past-float64
check / check (push) Successful in 1m21s
4b871c2b12
Both sides added a line at the top of the Completed Steps in
docs/TODO.md; both are kept, this branch's first.

Model: opus-5-5
Author
Collaborator

FAIL: needs-rework

  1. internal/calc/calc.go, nonNegativePower: a fractional power still turns its base into a double first, and refuses it when the base is outside a double's range, even though the base is exact and the answer is an ordinary double. (2^1200)^0.5 is 2^600 (about 4.15e+180), (2^1024)^0.5 is 2^512, (2^-1200)^0.5 is about 2.41e-181 and 1e400^0.5 is 1e+200. All four get "That needs a number too large or too small for me.", although the bot now answers 2^1200 itself. #16 asks for every power path to be checked for this limit and for each case found to be fixed; the new (2^1200)^0.5 test instead keeps this one refused. Acceptable: a fractional power of an exact base outside a double's range is computed without turning the base into a double (for instance, split the base as m·2^k with big.Float's MantExp and raise each part in float64), and is refused only when the result is not a normal double; these four in the tests with their values; the README's refusal sentence and its 1e-400^0.5 example updated to match.

Judgement call, not raised: answering 1e-310 again follows the rule on #3 (comment), as the reason for refusing it on #11 (writing it through a double) is gone.
Judgement call, not raised: 17 significant digits past the range is accepted; an input exactly halfway between two 17-digit values, such as 1.00000000000000015e-400, can round either way rather than to the even digit, and both are equally near.

Model: opus-5-5

**FAIL: needs-rework** 1. `internal/calc/calc.go`, `nonNegativePower`: a fractional power still turns its base into a double first, and refuses it when the base is outside a double's range, even though the base is exact and the answer is an ordinary double. `(2^1200)^0.5` is `2^600` (about 4.15e+180), `(2^1024)^0.5` is `2^512`, `(2^-1200)^0.5` is about 2.41e-181 and `1e400^0.5` is `1e+200`. All four get "That needs a number too large or too small for me.", although the bot now answers `2^1200` itself. https://git.eeqj.de/sneak/simplexcalc/issues/16 asks for every power path to be checked for this limit and for each case found to be fixed; the new `(2^1200)^0.5` test instead keeps this one refused. Acceptable: a fractional power of an exact base outside a double's range is computed without turning the base into a double (for instance, split the base as m·2^k with `big.Float`'s `MantExp` and raise each part in float64), and is refused only when the result is not a normal double; these four in the tests with their values; the README's refusal sentence and its `1e-400^0.5` example updated to match. Judgement call, not raised: answering `1e-310` again follows the rule on https://git.eeqj.de/sneak/simplexcalc/issues/3#issuecomment-105003, as the reason for refusing it on https://git.eeqj.de/sneak/simplexcalc/pulls/11 (writing it through a double) is gone. Judgement call, not raised: 17 significant digits past the range is accepted; an input exactly halfway between two 17-digit values, such as `1.00000000000000015e-400`, can round either way rather than to the even digit, and both are equally near. Model: opus-5-5
clawbot added needs-rework and removed needs-review labels 2026-09-29 09:18:38 +02:00
clawbot added 1 commit 2026-09-29 09:38:07 +02:00
A fractional power turned its base into a double first and refused a
base outside the normal range of a double, so (2^1200)^0.5, (2^1024)^0.5,
(2^-1200)^0.5 and 1e400^0.5 were refused although each answer is an
ordinary double. Such a base is now brought into that range by square
roots taken from its exact value in a big.Float, at most three under the
4096-bit limit, with the exponent doubled for each, and only a result
that is not a normal double is refused. The tests give these powers and
the edges of the range their values, and the bounded-work test covers a
base that needs three roots. The README's refusal sentence and example
are updated.

Model: opus-5-5
clawbot added needs-review and removed needs-rework labels 2026-09-29 09:39:03 +02:00
Author
Collaborator
  1. Fixed in c4094ff: a base outside a double's normal range is brought into it by square roots taken from its exact value, so only a result that is not a normal double is refused; the four powers and the edges of the range are tested with their values, the bounded-work test covers a base that needs three roots, and the README's refusal sentence and example are updated.

No other value is turned into a double before it must be: what remains is a base inside the range and the exponent of a power computed in float64, which math.Pow takes as doubles.

Model: opus-5-5

1. Fixed in `c4094ff`: a base outside a double's normal range is brought into it by square roots taken from its exact value, so only a result that is not a normal double is refused; the four powers and the edges of the range are tested with their values, the bounded-work test covers a base that needs three roots, and the README's refusal sentence and example are updated. No other value is turned into a double before it must be: what remains is a base inside the range and the exponent of a power computed in float64, which `math.Pow` takes as doubles. Model: opus-5-5
Author
Collaborator

PASS: the rework answers exact results past a double's range, and fractional powers of such numbers, with correct values, and meets every item of #16 that a review can check.

Judgement call, not raised: a fractional power carries the rounding of math.Pow, which for a large base can reach the last two or three digits shown ((2^1200)^(1/3) is 2.5822498780869e+120, and 2^400 is 2.5822498780869086e+120). This is no worse than for a base inside the range, and is accepted as float64 rounding under #3 (comment).
Judgement call, not raised: after two square roots, the test for a base that needs three, (2^-4094)^0.125, has an exponent of 0.5, which math.Pow takes exactly, so the test would still pass with the third root missing. The loop's condition itself is tested by 1e-310^0.5.

Model: opus-5-5

PASS: the rework answers exact results past a double's range, and fractional powers of such numbers, with correct values, and meets every item of https://git.eeqj.de/sneak/simplexcalc/issues/16 that a review can check. Judgement call, not raised: a fractional power carries the rounding of `math.Pow`, which for a large base can reach the last two or three digits shown (`(2^1200)^(1/3)` is `2.5822498780869e+120`, and `2^400` is `2.5822498780869086e+120`). This is no worse than for a base inside the range, and is accepted as float64 rounding under https://git.eeqj.de/sneak/simplexcalc/issues/3#issuecomment-105003. Judgement call, not raised: after two square roots, the test for a base that needs three, `(2^-4094)^0.125`, has an exponent of `0.5`, which `math.Pow` takes exactly, so the test would still pass with the third root missing. The loop's condition itself is tested by `1e-310^0.5`. Model: opus-5-5
clawbot merged commit 0b9121a806 into next 2026-09-29 09:56:56 +02:00
clawbot deleted branch issue-16-exact-results-past-float64 2026-09-29 09:56:56 +02:00
Sign in to join this conversation.
No Reviewers
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: sneak/simplexcalc#18