Skip to content

fix: use log-space computation in geometric_mean to prevent float underflow#347

Open
Grizouforever wants to merge 1 commit intoAffineFoundation:mainfrom
Grizouforever:fix/geometric-mean-float-underflow
Open

fix: use log-space computation in geometric_mean to prevent float underflow#347
Grizouforever wants to merge 1 commit intoAffineFoundation:mainfrom
Grizouforever:fix/geometric-mean-float-underflow

Conversation

@Grizouforever
Copy link
Copy Markdown

Summary

  • Fixes Bug: geometric_mean underflows to 0.0 with many small positive values #346geometric_mean returned 0.0 incorrectly when iterative multiplication of many small positive values underflowed in IEEE 754
  • Replaces the product loop with a numerically stable log-space computation: exp((1/n) * Σ log(vᵢ))
  • Preserves all existing behavior: zero/negative inputs still return 0.0, empty list returns 0.0, the smoothed-epsilon path is unchanged

Root Cause

# Before — underflows to 0.0 for e.g. [1e-200] * 1000
product = 1.0
for v in values:
    product *= v
return product ** (1.0 / n)

IEEE 754 doubles underflow to 0.0 when the running product drops below ~5e-324. With 1000 values of 1e-200, the true product is 1e-200000, which is far below that floor.

Fix

# After — numerically stable across full positive float range
try:
    log_mean = sum(math.log(v) for v in values) / n
    return math.exp(log_mean)
except (ValueError, OverflowError):
    return 0.0

Test plan

  • geometric_mean([2.0, 8.0]) still returns 4.0
  • geometric_mean([1e-200] * 1000) returns ~1e-200 instead of 0.0
  • geometric_mean([0.5, 0.0, 0.5]) still returns 0.0
  • geometric_mean([]) still returns 0.0
  • Existing test suite passes (pre-existing import errors in tests/ are unrelated to this module)

🤖 Generated with Claude Code

…erflow

When geometric_mean receives many small positive values (e.g. 1e-200),
iterative multiplication underflows to 0.0 in IEEE 754, producing an
incorrect result. Replace the product loop with a log-space computation
(sum of logs divided by n, then exp) which is numerically stable across
the full range of positive floats.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
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.

Bug: geometric_mean underflows to 0.0 with many small positive values

1 participant