Let Equals match a number against a typed number like 130 (#224)

The float tolerance from the last commit never reached the case it was
built for. The inputs of Equals are of type any, and their inline field
is a text field. A typed 130 therefore arrives as the string "130", and
the tolerance only applied when both sides were real numbers. The node
fell back to comparing "129.99999999999997" with "130" as text.

- A number against a text that parses as a number now uses the same
  1e-9 rule as two numbers.
- An empty text does not count as 0.
- Two texts are still compared as text, so "1.0" and "1" stay
  different.
- Compare was not affected, its inputs are real number fields.

Tests:
- 3 new cases in node-catalog.test.ts: 129.99999999999997 vs "130"
  is equal, 0 vs "" is not, "1.0" vs "1" is not.
- Counter-check: with the old rule (two real numbers only) exactly the
  "130" case fails. Original restored and compared with cmp.
- ./check.sh: 156 files, 2314 tests, CHECK EXIT 0 (before 2311).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
adminandClaude Opus 5.5 committed 2026-09-24 08:44:25 +02:00
1 parent 9d6a0aebd3
commit 5bf1ee7a4e
2 files changed
+23 -3

No files matched your search

+15 -3
View File
@@ -1,5 +1,5 @@
import type { NodeDef } from '../../NodeRegistry';
import { asEntity, asString, nearlyEqual } from '../../values';
import { asEntity, asString, nearlyEqual, type Value } from '../../values';
import { any, bool } from '../shared';
export const Equals: NodeDef = {
@@ -15,9 +15,21 @@ export const Equals: NodeDef = {
const a = asEntity(inputs.a);
const b = asEntity(inputs.b);
if (a || b) return { outputs: { result: a === b } };
if (typeof inputs.a === 'number' && typeof inputs.b === 'number') {
return { outputs: { result: nearlyEqual(inputs.a, inputs.b) } };
// An inline field on an `any` pin is text, so a typed 130 arrives as "130": with a number on
// the other side it still counts as that number (#224).
const x = numberOf(inputs.a);
const y = numberOf(inputs.b);
if (x !== null && y !== null && (typeof inputs.a === 'number' || typeof inputs.b === 'number')) {
return { outputs: { result: nearlyEqual(x, y) } };
}
return { outputs: { result: asString(inputs.a) === asString(inputs.b) } };
},
};
/** A number, or text that is one ("130", " 1.5 "); empty text is not 0 here. */
function numberOf(value: Value | undefined): number | null {
if (typeof value === 'number') return value;
if (typeof value !== 'string' || value.trim() === '') return null;
const n = Number(value);
return Number.isFinite(n) ? n : null;
}