Published Updated
SciPy returns zero for a representable Student-t tail
A Welch test and two lower-level Student-t functions return zero for a positive subnormal probability that remains representable in binary64.
Current upstream disposition
SciPy contributor mdhaber reproduced the positive reference value with the current development version and the arbitrary-precision MPArray backend. That run returned 3.504710110487091...e-316 through the otherwise unchanged stats.ttest_ind interface.
The contributor advised against spending maintainer time on preserving the bounded subnormal range in the NumPy backend. MPArray already supports much smaller probabilities, while this reported case does not change an ordinary significance decision. Licklider accepts that prioritization and will not pursue a NumPy-backend correction through this report. The issue was closed as not planned on September 30, 2026. No NumPy-backend fix was merged for this report.
This disposition records a practical trade-off: the demonstrated numerical difference remains, while upstream recommends a different backend for users who need these probabilities. The discussion does not measure how often this failure occurs in real workflows.
A positive Welch p-value disappears
SciPy 1.18.1 returns a two-sided Welch p-value of exactly 0.0 for two groups whose mathematical p-value is approximately3.504710110487091e-316. That probability is extremely small, but it remains representable as a positive binary64 subnormal value.
Tasuku Kobayashi reported the case in SciPy issue #26290 on September 27, 2026. The NumPy-backend behavior remains unchanged; the upstream response identifies MPArray as the available path when these extreme tails matter.
A small exact dataset reproduces the zero
Each group contains 201 exactly representable observations. The first has 100 copies of -1, one 0, and 100 copies of 1. The second is the first group shifted upward by 12. Their means are 0 and 12, and both unbiased sample variances are exactly 1.
import warnings
import numpy as np
import scipy
from scipy import special, stats
x = np.r_[np.full(100, -1.0), 0.0, np.full(100, 1.0)]
y = x + 12.0
with warnings.catch_warnings(record=True) as caught:
warnings.simplefilter("always")
result = stats.ttest_ind(x, y, equal_var=False)
sf = stats.t.sf(abs(result.statistic), result.df)
cdf = special.stdtr(result.df, -abs(result.statistic))
print(scipy.__version__)
print(result)
print(sf, cdf)
print([str(w.message) for w in caught])1.18.1
TtestResult(statistic=-120.29962593458053, pvalue=0.0, df=400.0)
0.0 0.0
[]The statistic and 400 degrees of freedom are correct, and the recorded run emits no warning. The same input returned a positive two-sided value of3.5047101e-316 in SciPy 1.16.1, while SciPy 1.17.0 and 1.18.1 returned zero. The lower-level stats.t.sf and special.stdtr calls also return zero, placing the observed loss at or below the Student-t probability calculation. The report does not claim a more specific internal cause.
An independent reference stays positive
For this dataset, the squared statistic is exactly 14,472 and the two-sided probability is the regularized incomplete-beta valueI_(50/1859)(200, 1/2). A 130-digit calculation gives3.5047101104870913387606868475703e-316. Converting that result to a Python float produces the positive value 3.5047101e-316.
The report also checks the result with a separately evaluated positive-term series. Simple analytical bounds place the p-value strictly between3.457494873756592e-316 and 3.504951044561724e-316. Both checks establish that the mathematical probability is positive and does not have to round to zero in binary64.
What the case establishes
This example does not change a decision at the 5% level: both zero and the reference value are far below 0.05. It does show that an ordinary finite dataset can make a Welch result lose the distinction between an extremely small finite probability and mathematical zero. That distinction can matter when later work transforms, ranks, stores, or combines reported probabilities.
The finding is limited to the reported inputs, functions, and versions. It does not estimate how often practical analyses enter this range, establish the root cause, or provide a general repair. It also does not expand nomue's supported scope or change nomue Protocol Release 1.
Public evidence
- SciPy issue #26290— complete reproducer, version comparison, high-precision reference, independent series check, bounds, and current upstream status
- SciPy contributor response— MPArray reproduction, recommended backend path, and prioritization rationale
- Reporter’s acceptance of the proposed disposition— agreement to close without a NumPy-backend repair and prioritize reports affecting realistic workflows, decisions, or commonly used numerical ranges
- SciPy
ttest_inddocumentation— public documentation for the reported Welch-test entry point - SciPy
stdtrdocumentation— public documentation for the lower-level Student-t cumulative distribution function