Let Compare and Equals treat float noise as equal numbers
A graph that checks "time - late == 6" after On timer (#224) failed, because the difference comes out as 5.999999999999972. Both values are sums of measured frame times, and they round along different paths. The only workaround was a Round node in front of every comparison. - New helper nearlyEqual in values.ts. Two numbers count as equal when |a - b| <= 1e-9 * max(1, |a|, |b|). The tolerance grows with the size of the values, so it holds for hours of summed dt. - Compare uses the rule for all six operators. "<" and ">" only hold when the values are not nearly equal, "<=" and ">=" also hold when they are. So "==" and ">" are never true at the same time. - Equals uses the same rule when both inputs are real numbers. Objects still compare by identity, everything else as text. The node description says so. - The tolerance is fixed, there is no parameter on the node. Physics values come from float32 in Rapier and are not covered on purpose. - The log display is unchanged and still prints the raw number. Tests: - ./check.sh: 156 files, 2311 tests, CHECK EXIT 0 (before 2300). - 11 new cases in node-catalog.test.ts, including the value from the log against 6, growth with magnitude, 6.001 != 6 and 1e-6 > 0. - Counter-check exact compare: exactly the 8 noise cases fail. - Counter-check "<"/">" without the exclusion: exactly 2 cases fail. - No e2e change, the check sum stays at 1374. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
6fecb2e841
commit
9d6a0aebd3
4 files changed
+85
-9
No files matched your search
@@ -25,6 +25,16 @@ export function isEntity(value: Value | undefined): value is EntityHandle {
|
||||
return typeof value === 'object' && value !== null && ENTITY_HANDLE in value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether two numbers are the same up to float noise (#224): a relative 1e-9, never less than 1e-9
|
||||
* absolute. `time - late` lands 1e-14 off a whole second, and after hours of summed `dt` the error
|
||||
* still stays far below this, while 6 and 6.001 remain apart.
|
||||
*/
|
||||
export function nearlyEqual(a: number, b: number): boolean {
|
||||
if (a === b) return true;
|
||||
return Math.abs(a - b) <= 1e-9 * Math.max(1, Math.abs(a), Math.abs(b));
|
||||
}
|
||||
|
||||
/** A list of anything a data edge carries – a handle among the items is what `isList` cannot say. */
|
||||
function isValueList(value: Value | undefined): value is ValueList {
|
||||
return Array.isArray(value);
|
||||
|
||||
Reference in new issue
Block a user