Grasshopper Python - decimal tolerance

Dear all,
I make a short python code to split diameter and thickness of pipes from an input string and then convert them into float. However the out put figures are not exactly as input.
ie: 190.7 ===> 190.699999999999
Many thanks if you could advise how to fix it.
Thank you in advance.
Loc.

a = 13.946
print(a)
13.946
print(“%.2f” % a)
13.95
round(a,2)
13.949999999999999
print(“%.2f” % round(a, 2))
13.95
print(“{:.2f}”.format(a))
13.95
print(“{:.2f}”.format(round(a, 2)))
13.95
print(“{:.15f}”.format(round(a, 2)))
13.949999999999999

I think you can use “Round” function,
But I’m not sure how to apply on that data type, may be after conversation with index you can fix it.

(I copied this code from stack overflow)
You can try

No need to worry, this is because of the float representation of decimal numbers as binary fractions.

What you have called outer_diameter is the output of the script (i.e. the result of the print function). Python doesn’t round it unless you ask.

Grasshopper does the rounding for you. See below:

To know more about float representation, see the Python docs

As @Anil_verma mentioned I use the round function for situations like this all the time. I have had no issues with it.

Although there is no harm in using round, the value stored is still not the exact value:

  >>>print "{:.20f}".format(.1)      
  0.10000000000000000555
  >>>print "{:.20f}".format(round(.1, 2))      
  0.10000000000000000555

So if you want to save your fingertips some efforts, just don’t use round.
But again, there is no harm in using it, so it’s up to you :slightly_smiling_face:

round is useful for doing this sort of things:

  >>>x = round(.28, 1)
  .3

Where the value of the variable is actually modified.

Yeah I tend to you it to fulfill conditional statements. Sometimes when comparing diameters of circles or lengths of lines I have found using the round function handy to fulfill that condition of interested.

Good to know though !

Rounding may work for comparison and it sounds like you had it working most of the times but a more typical way is abs(x - y) < tolerance

This avoids any issue with float precision and is guaranteed to work 100% of the time.

Anyway don’t fix it if it’s not broke!

2 Likes

@Jacques_Gaudin Thats good to know ! Thanks for showing me this !

For completeness, an example of what DOESN’T work:

>>>round(2.675, 2) == 2.68
False

This is because 2.675 has an exact value of 2.67499999999999982236431605997495353221893310546875 in Python… Ooops!

That’s not the case in IronPython:

1 Like

Ha! That’s a rather bad example then… I took it from CPython 2.7 docs. Seems to be implementation dependent.

But still, in Iron Python:

>>>0.1 + 0.2 == 0.3
False

whereas:

>>>x = 0.1 + 0.2
>>>y = 0.3
>>>abs(x - y) < 1e-6
True

Hehe, yeah it’s still a jungle in .NET land. Checking the distance between values against a tolerance is definitely “the way”, as you pointed out above :slight_smile:

1 Like