Skip to content

Missing bin due to floating-point error #282

@Fil

Description

@Fil
Member
const values = [0.9299999999999999, 1.07];
d3.bin().thresholds(500)(values).filter((d) => d.length);

this returns: [[1.07, x0: 1.07, x1: 1.0702]]; the first value has disappeared.

Activity

added
bugSomething isn’t working
on Mar 16, 2025
mbostock

mbostock commented on Mar 16, 2025

@mbostock
Member

The problem occurs in the nice subroutine where the domain is erroneously niced to [0.93, 1.07]; the assumption is that the nice domain must subsume the original domain, but that’s not true with this input. That’s because:

Math.ceil(0.9299999999999999 * -5000) / -5000 // 0.93

Also:

d3.nice(0.9299999999999999, 1.07, 5000) // [0.93, 1.07]

The niced domain should be [0.9298, 1.07] instead. We probably need a threshold test instead of assuming that ceil and floor produce the desired result.

mbostock

mbostock commented on Mar 16, 2025

@mbostock
Member

(That said, I’m curious where the 0.9299999999999999 is coming from? Because if we control that code, we should try to get it to generate 0.93 instead which would avoid this problem.)

self-assigned this
on Mar 16, 2025
linked a pull request that will close this issue on Mar 16, 2025
Fil

Fil commented on Mar 16, 2025

@Fil
MemberAuthor

This number is initially caused by a floating point error in this code I'm playing with:

  const data = [0, 2, ...Array.from({ length: 18 }, () => 1)]; // Array(20)
  const lo = d3.quantile(data, 0.05);
  const hi = d3.quantile(data, 0.95);
  const delta = (hi - lo) * 0.2;

  const bins = d3.bin()
    .thresholds(500)
    .value((d) => clamp(d, lo - delta, hi + delta))(data);

  return bins.filter((d) => d.length); // [Array(18), Array(1)] 🌶 there should be 20 total

  function clamp(x, lo, hi) {
    return x < lo ? lo : x > hi ? hi : x;
  }

(I've "fixed" my code by using 1/7 instead of 0.2…)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

bugSomething isn’t working

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

    Development

    Participants

    @Fil@mbostock

    Issue actions

      Missing bin due to floating-point error · Issue #282 · d3/d3-array