Skip to content

fix(dummies): draw decimal fractions from all 96 mantissa bits - #268

Merged
Reefact merged 1 commit into
mainfrom
claude/issue-206-discussion-ua180a
Jul 21, 2026
Merged

fix(dummies): draw decimal fractions from all 96 mantissa bits#268
Reefact merged 1 commit into
mainfrom
claude/issue-206-discussion-ua180a

Conversation

@Reefact

@Reefact Reefact commented Jul 21, 2026

Copy link
Copy Markdown
Owner

Summary

AnyDecimal never generated the upper half of any range. The sampling fraction was built from three non-negative Random.Next() draws over the full 96-bit mantissa denominator, so each limb's top bit stayed zero and the fraction capped near 0.5; every candidate fell in [min, mid) and the inclusive maximum documented on Between was unreachable. This fills all 96 mantissa bits so the fraction is uniform over [0, 1] and the whole range — up to the inclusive maximum — is reachable.

Type of change

  • Bug fix
  • New feature
  • Breaking change
  • Refactoring
  • Analyzer / diagnostic change
  • Tests
  • Documentation
  • Build / CI / tooling

Changes

  • Build the decimal sampling fraction from all 96 mantissa bits via random.NextBytes + three BitConverter.ToInt32, replacing the three non-negative Random.Next() draws that pinned each limb's top bit to zero (DecimalIntervalSpec.Generate).
  • Correct the stale [0, 1) comment to describe the real [0, 1] construction.
  • Add a seeded reachability regression test (AnyContinuousTests.DecimalBetweenReachesBothHalves) asserting that both halves of a range — and a value near the inclusive maximum — are observed.

Testing

  • dotnet build FirstClassErrors.sln
  • dotnet test FirstClassErrors.sln
  • Analyzer tests pass (FirstClassErrors.Analyzers.UnitTests)

Full solution: build clean (0 warnings); dotnet test FirstClassErrors.sln reports 0 failures across every test project, including FirstClassErrors.Analyzers.UnitTests (85) and Dummies.UnitTests (223) with the new reachability test.

Documentation

  • Public API / error documentation updated
  • README / doc/ updated
  • French translation (doc/handwritten/for-users/README.fr.md) updated if user-facing behavior changed
  • No documentation change required

The documented contract — Between yields values in the inclusive [minimum, maximum] range — does not change; this fix makes it hold. Seeded reproducibility within a version is preserved.

Architecture decisions

  • No architectural decision in this pull request
  • New decision recorded — ADR drafted as Proposed: ADR-____
  • Supersedes an existing ADR — successor proposed, status not flipped: ADR-____
  • ⚠️ Conflicts with an existing ADR — flagged for the maintainer: ADR-____

Checked against the ADR base: this is a sampling-construction bug fix, not a lasting decision. It stays compliant with ADR-0026 (single engine, single seed scope) — the engine and seed scope are unchanged.

Related issues

Closes #206

🤖 Generated with Claude Code

https://claude.ai/code/session_019Z8qWCLG88eE9brd7YwawW


Generated by Claude Code

AnyDecimal built its fraction from three non-negative Random.Next()
draws over the full 96-bit mantissa denominator. Each limb's top bit
was therefore pinned to zero, so the fraction never exceeded ~0.5 and
every candidate fell in [min, mid): the upper half of every range — and
the inclusive maximum documented on Between — was unreachable.

Fill all three mantissa limbs from NextBytes, yielding a genuinely
uniform fraction over the whole [0, 1] scale, and correct the stale
comment. Seeded reproducibility is preserved: the same seed still
replays the same sequence within a version. Add a seeded reachability
test proving both halves, and a value near the inclusive maximum, are
observed.

Refs: #206
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_019Z8qWCLG88eE9brd7YwawW
@Reefact
Reefact merged commit 0c506e4 into main Jul 21, 2026
15 checks passed
@Reefact
Reefact deleted the claude/issue-206-discussion-ua180a branch July 21, 2026 14:34
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.

Dummies: AnyDecimal never generates the upper half of a range

2 participants