Published
Large integers can change SciPy’s Mann–Whitney U decision
Eight distinct integers become artificial ties inside SciPy, changing an exact p-value from 1/35 to 2/35 without changing the original ordering.
Eight integers, the same ordering, a different decision
Adding the same integer to every observation preserves their order. A rank-based comparison should therefore give the same result. In the example reported to SciPy, that change moves the two-sided exact p-value from 1/35 ≈ 0.02857 to 2/35 ≈ 0.05714, crossing the conventional 5% significance threshold.
The input consists of two groups of four distinct int64 integers. SciPy converts them to floating point before assigning ranks. At an offset of 2**53, that conversion makes some distinct integers equal, creating ties that were absent from the original data.
Tasuku Kobayashi filed SciPy issue #26658 on November 9, 2026. The report is open; upstream confirmation and a repair are pending. The report’s automatic defect label is not maintainer confirmation.
A small reproducer with an exact reference
import numpy as np
from scipy.stats import mannwhitneyu
for offset in (0, 2**53):
x = np.array([offset + i for i in range(4)], dtype=np.int64)
y = np.array([offset + i for i in range(4, 8)], dtype=np.int64)
assert len(set(map(int, np.concatenate([x, y])))) == 8
print(offset, mannwhitneyu(x, y, method="exact"))Every value in the first group is below every value in the second, so its U statistic is zero. There are 70 ways to allocate eight distinct ranks between groups of four. One allocation lies at each extreme, giving the two-sided exact probability 2/70 = 1/35 at either offset.
| SciPy | U after offset | Exact p after offset |
|---|---|---|
| 1.16.3 | 0 | 0.02857142857142857 |
| 1.17.0 | 1 | 0.05714285714285714 |
| 1.18.1 | 1 | 0.05714285714285714 |
| 2.0.0.dev0+git20261105.f890ba5 | 1 | 0.05714285714285714 |
All four environments return U=0 and p=1/35 without the offset. The recorded runs used NumPy 2.3.5 and Python 3.12.14 on Linux x86_64, without warnings for these calls. The introducing commit has not been bisected.
Preserve the data property that the method depends on
The original integer arrays retain all eight distinct values. The loss happens inside input validation, at force_floating=True, before rank generation. Directly ranking the original pooled integers preserves ranks 1 through 8. This differs from the batch-method report: it uses one sample pair and fails even with an explicitly selected exact method.
This is a synthetic boundary example, not an estimate of its frequency in research datasets. It does not establish an effect on SciGround’s production path, a generally validated patch, or a new supported analysis. The engineering lesson is to check that a tool’s input conversion preserves the ordering on which a rank-based calculation depends.
The public upstream report contains the full reproducer, output, environment and comparison with related issues. The inspected fixed main source retains the conversion; the executed development build is the one listed above.