Equals component makes no sense. I call this a bug

0.1 = 0.1 = False?

I’ve seen these topics explaining the problem:

But doesn’t it make more sense that grasshopper is showing you a number that actually is the value? Like round it off somewhere in the background so I don’t need to deal with finding what’s going wrong and trying to fix this hidden black magic? Or is this really just not possible?

1 Like

Rounding the values solves one problem by creating another. If you want to compare numbers based on how they look rather than based on what they are, you should use text comparisons.

The only solution which makes any kind of sense is to provide better comparison components which specifically target absolute, relative and topological tolerances.

1 Like

These three approaches basically mean…

Absolute equality, with a threshold t:
a=b if and only if abs(a-b) < t

Relative equality with a factor f:
a=b if and only if abs(a-b)<f\cdot max(a,b)

Topological equality with a threshold k:
a=b if and only if abs(top(a)-top(b)) < k

Where top Converts the floating point number into the integer with the equivalent bit pattern.

Just out of curiosity: which problem does it create?

I’m not sure I understand the 3 differences but having the option to choose what I need works for me. I’ve ran into this problem a few times and it takes a bit of time in a bigger definition to find this as being the problem. To me it makes sense to get the number that you see going in as the actual value whether it’s text or not. And I imagine for beginners this also makes most sense, judging by how regularly this question pops up as a topic over the years. But maybe I’m overlooking problems which you understand better than I do and it would cause a lot of issues in case it gets changed.

From reading the docs https://rhino.github.io/components/mathematics/equality.html I can’t tell whether Grasshopper is checking for equality within the (user defined) CAD tolerance or with floating point value. By some trial and error it seems that the problem comes from floating point maths.
I think the documentation should be improved given that this is a recurring issue. It’s not really reasonable to expect GrassHopper users to just know this stuff.

1 Like

It rounds your values, and thus destroys a lot of information. Values which are supposed to be different will suddenly become equal.

It’s certainly subtle and the method and parameters you choose matter a great deal, so one needs to understand both the underlying mathematics of the problem at hand and the underlying mathematics of the comparison method. It’s fair to say few people are in this category.

Absolute tolerances are good for when the numbers represent distances or angles. Your manufacturing method has a certain accuracy and there’s no point spending more decimal places than needed.
The problem with absolute tolerances is that they don’t scale. When dealing with small numbers you have a lot of accuracy. For example there are loads of distinct values between 1.0 and 2.0. But as the numbers get bigger, so do the gaps between them. There are far fewer distinct values between 1,000,001 and 1,000,002.
Arithmetic inaccuracies affect the least significant digits of numbers first, but those digits have a much bigger magnitude when the numbers are big.

Relative comparisons sort of deal with this issue, but the choice of factor is difficult.

Topological comparisons cut out the middleman, by testing how many distinct values there are between numbers. It automatically scales with the magnitude of the values in question, and the thresholds are usually easy to remember values like 5 or 10 or 50.

Sadly, sometimes you need more than one comparison to get the real answer you’re looking for.

Floating point maths is hard

1 Like

A lot of information which many, if not most, users don’t need? How about a button to put Equals into “geek-mode” in case you need that and otherwise by default take the value it shows in panel?

I find the mathematics behind it interesting to know about (thanks a lot for the explanation, by the way) but to be honest I don’t think the end user should deal with it by default.

Surely you have a better idea what most people use grasshopper for than I do, but to me it just doesn’t make sense to show “0.1” if it’s not equal to “0.1”. Perhaps one could define a tolerance in grasshopper to solve this, just like in Rhino? And by default it takes your tolerance from Rhino for rounding off values?

That is actually a pretty good suggestion. BTW, this is great discussion, the equality issue has tripped me up a few times,

How about a equality component which takes an integer representing the number of decimals and setting that input to the same number as the display decimal cut-off by default.

Basically equality with rounding build in. It would be functionally identical to absolute tolerance, but you get to say 6 rather than 0.000001 when specifying the tolerance.

Sure, sounds like a good solution to me. But then what about smaller than and larger than, you’d get the same input there?

Good question, hadn’t thought about that yet.

That would work, I could see using this to troubleshoot a model, for example feed a series into the accuracy, 3, 4, 5, 6, 7, and see where the behavior changes to identify problem geometry.

I wonder if this couldn’t be solved by adding a third input to the component for the tolerance. It would have a default value if nothing was hooked up, or people could plug in a different value or even wire up an expression to it if they found necessary.

The main debate would be what the default value should be, if it takes the document tolerance, changing that value in the Rhino document could change the result in GH, i.e. the definition becomes Rhino document-dependent… So I guess I would favor having an invariable constant (maybe square root epsilon?) in this case, and force the user to consciously add a tolerance if they needed. But that probably wouldn’t please all of the people…

If I understand correctly the MS Excel resolves this by explicitly checking for floating point errors, which sounds like a very hard problem once you’ve multiplied up and back down by a few orders of magnitude. It still leaves the unexpected behaviour when the GH tools give a different equality result from integrated Python, etc.

Dunno, Python has the same limitations:

print a==b
>>> False

Yes I mean if the behaviour is changed in the Grasshopper tool then people will be caught out when comparing their Python or C script with the Grasshopper tool…

Pufferfish has implemented it like this. (It’s called Equality within Tolerance)
By the way I’d have no problem to have this standard value to be the one of the Rhino doc.

Well, I expect that people who are programming with Python or other languages should know about this stuff… But that’s also why I suggested that the default above be similar to what it does now and that you have to input a value if you want to change the behavior…

1 Like