Mesh.Vertices accuracy seems wrong, why?

I recorded RH-58628 to keep track of this problem.

Right now, users can use the mesh.Vertices.GetPoint3dAt() function to look at the double precision vertex of the mesh. This is however a little less easy to find than the indexer [], which returns the single precision.

3 Likes

From the Python floating point tutorial perhaps my favourite bit is this:

print ( 0.1 + 0.1 + 0.1 == 0.3)

Just paste that in EditPythonEditor and run it :slight_smile:

4 Likes

image

Ok, I am logging off and will stare at the sky for a while.
My world just crumbled.

1 Like

Welcome to the wondrous world of programming!

3 Likes

OK so I guess that with my new “knowledge” it refines to a wish:
I wish that the coerced 3D point of the single precision indexed point results in the same value as the printed value of that given point.
(Is that accurately stated? I feel I know nothing now… :wink: )

Printing single precision, as you can see, has less accuracy than double precision.
We can’t have the indexer return doubles now, because it would break existing plug-ins. And we are trying to keep new versions of RhinoCommon compatible with older plug-ins.

We could deprecate the indexer, and print a warning that points to this or a similar discussion. It could also suggest the GetPoint3dAt method. Would that be enough?

:grimacing: I don’t know anyting any more… Nathan just broke my mind…

A = (0.1+0.1+0.1)
B = 0.3
print A == B

It’s False… Hahahahahaaa…

Give it a few days :slight_smile:

2 Likes

Maybe that is what happens to the binary value.
And then the same (binary) number is simply formatted as decimal using different precisions …
… I guess since one is a 32 bit value and the other a 64 bit value.

EDIT:

EDIT:

You may want to use the “r” (roundtrip) format specifier:
https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-numeric-format-strings

1 Like

After 20 years of math,geometry programming I ended up to think geometry like what happens in the real world, a point a line and a surface do not exist. They are balls, cylinders and skins with a epsilon radius/thickness. This helps to make robust coding (at least I hope)
Gd

This still baffles my mind.
4 years in and I still don’t understand, but it now makes sense why rockets fall out of the sky every now and then… Since computer logic is so different from human logic.

Proposal:
Would it be possible to add a decimal limiter for all calculations in python so it never uses more than 15 decimals? Or use the accuracy of the Rhino document, without having to use round() on every thing we check?
From this simple example it seems like 15 decimals is the turning point.

A = (0.1+0.1+0.1)
B = 0.3

print "A=",A," B=",B
if A == B:
    print "A = B"
else:
    print "they are not the same"
    print "the difference is", A-B

for decimals in range(13,20):
    if round(A,decimals) == round(B,decimals):
        print "With ",decimals,"decimals they are the same"
    else:
        print "They are NOT the same, with ",decimals, "The difference is",round(A,decimals)-round(B,decimals)

A= 0.3 B= 0.3
they are not the same
the difference is 5.55111512313e-17
With 13 decimals they are the same
With 14 decimals they are the same
With 15 decimals they are the same
They are NOT the same, with 16 The difference is 1.11022302463e-16
They are NOT the same, with 17 The difference is 5.55111512313e-17
They are NOT the same, with 18 The difference is 5.55111512313e-17
They are NOT the same, with 19 The difference is 5.55111512313e-17

It is not possible to do that on the operator level, or at least not smart.

Instead you’ll have to change your logic for comparison.

And because of these imprecisions we have equality checks that allow you to specify a precision you know will work for your cases. In RhinoCommon we have under Rhino.RhinoMath.EpsilonEquals(a, b, epsilon) where epsilon would be the term specifying the precision. For instance epsilon = 0.000001.

1 Like

Do you happen to know whether RhinoPython Floats are single or double precision? I read on the internet that most Pythons use doubles, but Holo’s example looks more like singles. On the other hand I’m not sufficiently expert to know.

Yeah, that makes sense from the computer-math perspective, it just doesn’t make sense from a people-math perspective. I find it really strange that this human-computer-human conversion is allowed to end up with false results. After all computers are here to assist us, not cause issues for us :slight_smile:
Simple math should in other words just work according to our ten digit rules. Baffling, but understandable, yet my user-oriented-designer brain just can’t let this one pass.

Take a look at this example, it ONLY works when A, B or C equals 0.3. Now how is that logical for a new user?

import random

limit = 10000
n = 0
target = 0.3

while True:
    n += 1
    if n> limit: break
    A = round(random.random(),1)
    B = round(random.random(),1)
    C = round(random.random(),1)
    if (  A + B + C ) == target:
        print "It took ",n,"iterations to get the target",target
        print "A=",A," B=",B," C=",C
        break

BUT if I change the target to 0.4 then it handles all alternatives (0.1+0.1+0.2 or 0.2+0.2 or 0.1+0.3 or 0.4)
Go figure…

I think you’ll have to take this one up with processor/hardware designers. And maybe after that with programming language creators.

Yup, go to the source and make them force fewer decimals into account so python can be used as a reliable calculator… Hold my beer, I have Gates on speed dial so this should be an easy fix :wink:

I think this library might help:

if you want to retain sanity don’t read here

https://en.cppreference.com/w/c/numeric/math/nextafter

those will get you the “next” float/double from a given one

Yeah… nah… I had a look and think I’ll rather grab a beer today… and tomorrow too, just to be sure!
:smiley: Thanks though. This stuff hurts, but in a fascinating way that leaves me wanting more in a strange way… :beers:

2 Likes