| 90 | // own digit count and compare as integers, tolerating a rounding difference of |
| 91 | // a few in the last place — so a value the tool rounded at its last digit (and |
| 92 | // any carry that produced) still counts as agreeing to that many digits. |
| 93 | function matchingSigDigits(a, b) { |
| 94 | const na = sciNorm(a), nb = sciNorm(b); |
| 95 | if (!na || !nb) return na === nb ? 99 : 0; |
| 96 | if (na.sign !== nb.sign || na.E !== nb.E) return 0; |
| 97 | const L = na.digits.length; |
| 98 | const toolDigits = na.digits; |
| 99 | const refDigits = nb.digits.length >= L ? nb.digits.slice(0, L) : nb.digits.padEnd(L, '0'); |
| 100 | const av = BigInt(toolDigits), bv = BigInt(refDigits); |
| 101 | const d = av > bv ? av - bv : bv - av; |
| 102 | if (d <= 2n) return L; // agree to all L digits (last-digit rounding ok) |
| 103 | return L - String(d).length; // first differing digit is at L - len(diff) |
| 104 | } |
| 105 | |
| 106 | // Normalize any integer-ish string ("123", "12e+3", "1.2e+3", "12300") to a |