Skip to content

Shrink.float improvement - #360

Merged
jmid merged 10 commits into
c-cube:mainfrom
jmid:shrink-float-polish
Oct 30, 2025
Merged

Shrink.float improvement#360
jmid merged 10 commits into
c-cube:mainfrom
jmid:shrink-float-polish

Conversation

@jmid

@jmid jmid commented Oct 28, 2025

Copy link
Copy Markdown
Collaborator

This PR slightly improves the QCheck.Shrink.float algorithm from #357.

Specifically, when shrinking the leading digit, e.g., 7 in 7.3542e45 to 1.3542e45,
the PR explores using the existing int shrinker (using repeated halving) to shrink the distance
rather than repeated subtraction of 1..

The first commit 3182638 documents the current behavior, whereas commit 7924e13 then documents the improvement.

Looking at the updated expect test outputs in 14bcaaa I'm however unsure whether this should be merged.
While the updates document fewer shrink steps used, producing 5. rather than 4. as a counterexample
to "testinput <= pi" is unsatisfying.

@jmid
jmid force-pushed the shrink-float-polish branch from 14bcaaa to 2332a0c Compare October 30, 2025 08:52
@jmid

jmid commented Oct 30, 2025

Copy link
Copy Markdown
Collaborator Author

OK, I've now looked a bit more into this, refined it, and rebased it on top of #362.
The result is

  • a reduction in number-of-successful-shrink-steps, documented in the expect tests
  • producing nicer counterexamples (no more 5. rather than 4. as a counterexample to "testinput <= pi").

To read the improvements

  • 00df8de is the rebased, original proposal
  • e0b4ba6 shrinks the leading digit using Shrink.int directly rather than the weird "distance-to-1."
  • c18d01c swaps the order of the heuristics so that "reduce-precision-digits" happens before "reduce-leading-digit"

For now, I've kept the updates to all unit and expect test outputs triggered by each change.
Should anyone be reading this

  • the above commits are intended as 3 steps of heuristic refinements
  • the change in unit/expect test outputs don't have to be read commit-by-commit

Surely more improvements can be made, but I'm at a point of declaring "good-enough" ™️

FTR, the combination of float_suff_different and "same or shorter string rendering" is tricky to revise:

  • The 0.0001% threshold means 1.000001 is hard to reduce (moving threshold moves the problem)
  • "Shorter string rendering" uses Float.print which writes out 5e6 as the longer "5000000.", but switching to Printf.sprintf "%e" writes out 50. as the longer "5.000000e+01"
  • We still would like to keep the number of shrinking candidates down, as just adding more will blow up combinatorially, e.g., for float list * float list

@jmid
jmid merged commit f3f0e55 into c-cube:main Oct 30, 2025
24 checks passed
@jmid
jmid deleted the shrink-float-polish branch October 30, 2025 13:55
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant