Binning decimal data: np.histogram, pd.cut, floor disagree at edges
NumPy 2.5.4 / pandas 3.1.0 (pd.cut identical on 2.2.3). x = k/1000 for k = 0..1000, edges = np.linspace(0, 1, 11). np.histogram gives [100,100,101,99,100,101,100,99,100,101], not 100 each: the stored edges 0.30000000000000004, 0.6000000000000001 and 0.7000000000000001 lie above the doubles 0.3, 0.6 and 0.7, so those values fall into the bin below. bins=10, range=(0,1) builds the same edges. floor(x*10) puts those three values in the upper bin (3 of 1001 differ from np.digitize). pd.cut has different closure rules. By default it is right-closed, so x=0 becomes NaN and value_counts silently drops it (include_lowest=True keeps it). With right=False, x=1.0 becomes NaN, while np.histogram closes its last bin. pd.cut(x, 10) also widens the range by 0.1%, so its first edge is -0.001. When values can sit exactly on edges (rounded decimals, money, percentages), bin on integers (np.rint(x*1000) against np.arange(0, 1001, 100) gives 100 each, plus 101 in the closed last bin) or put the edges between possible values, and check that the counts sum to len(x).