RC3 - float conversion when assigning to FloatProperty gives incorrect results

Hi @brecht, I think I’ve found a bug or at least something that’s not documented that should be, could be similar to what https://devtalk.blender.org/t/full-precision-float-vertex-colors/4706 is about.

Here’s what I am finding, I am doing this in the python console of RC3, build hash - 507ffee6e1f4 on a macintosh running 10.14.5.

>>> time.time()
1564448212.9361138

>>> C.window_manager.cr.cloud_system_issues[2].time_logged = 1564448212.9361138
>>> C.window_manager.cr.cloud_system_issues[2].time_logged
1564448256.0

As you can see, I am assigning a python float type to a FloatProperty called “time_logged” and its screwing the value up. This is causing inconsistencies in the value expected which then show up as the wrong time for entries in a log (for my use case it makes the log useless).

So,

  1. Is this intentional? and if so
  2. how do I get around the conversion? or if not
  3. should I file a bug report?

Thanks mate!

James

A float has only about 7 decimal digits of precision. The number you are assigning has 17 digits, so will lose precision when assigned to a float. As you can see, the number printed back agrees with your assigned value to the first 7 digits (actually 8 in this case).

1 Like

It is important to note that this is a limitation on Blender’s side. Python allows for much bigger (or infinite?) number of decimal digits of precision. So, some sort of validation for that could be implemented on the API side.

1 Like

But it is called FloatProperty. Which hopefully people understand as meaning IEEE single precision floating point. (If they don’t then I suppose that could be documented in the Blender API Documentation for FloatProperty.) That should be clue enough that your precision will be limited if you store something in it.

What kind of validation do you think could be implemented on the API side? Since Python uses (on “almost all platforms”) IEEE double precision floating point, all intermediate values and values assigned to FloatProperty will likely be double precision. Yes, a warning could be printed if a double precision number can not be exactly represented as a single precision number, but that is not likely to be useful. Think of 1/3 – the double approximation to that number will not be exactly representable as single precision float. Do you really want a warning when assigning 1./3. to a FloatProperty?

P.S., to the original poster’s question of “how do I get around the conversion”, the only real possibility is to either use multiple values to hold the time output (e.g., if the integer part of time doesn’t exceed 2**32, then you could store the time in two ints: the integer part of the time and the fractional part of the time times 1 million, say; or use even more integers to store the integer part, like the integer part mod 1 billion and the integer part divided by 1 billion); or you could reduce the number of digits needed to log your time by subtracting some large number that represents a time in the past that you will never log, and thereby hopefully getting values with only a few digits in the integer part.

Some people coding add-ons and especially those not familiar with other languages than Python might expect the behavior of Python floats there, that’s why I am proposing an overflow check. That situation is exactly the reason for the TS’s question, I suppose.

1 Like

I assume you’re talking about a float as in a C float? If that is the case I think this should definitely be documented, there is no warning of loss of precision when assigning a python float to the FloatProperty in blender, neither is there anything in the documentation that the underlying type can’t represent a python float to the same precision.
The context leads me to believe that I can store a python float value in the property since;

  1. I am programming in the python language
  2. Using the blender python API
  3. The lack of any docs suggesting that the python float type is different in precision to the FloatProperty exposed by Blender’s python API

So from my perspective as an addon dev, I see all this as python. Granted there is a C backend, but python always has a C backend, even for its native float value as far as I understand it!

1 Like

Why not just do a type conversion and save it to a StringProperty?
e.g.: time_string_prop = str(time.time())
If the value is just going to a log file (and be converted to a string anyway), this would be a simpler workaround, no? I can’t see how this would cause problems unless you planned to do some kind of math on the value later.

Interesting, for me the opposite would make more sense. The FloatProperty is part of Blender’s python module and is intended to be used to get and set values inside Blender. For this reason I think it would be more natural to assume it was single precision to match Blender instead of having it contain data that Blender couldn’t make use of. Having a note that the FloatProperty is single-precision in the API docs wouldn’t hurt though.

1 Like

Math is definitely planned! Logging is more for users that might be curious when something happened. We will be using the time value elsewhere though.

Your perspective is interesting, I can see the logic in it, though for me, having a name like the ‘python api’ and being able to assign float values to the FloatProperty really doesn’t suggest to me that a different storage method is being used to the python one. So yeah, clearing that up in the API would be awesome!

I updated the source code so that the generated API docs clarify that FloatProperty holds single precision floating point numbers. I didn’t push regenerated docs to the api documentation on docs.blender.org, but the next time someone does, these changes should be there.

4 Likes

Hurray! Thanks Howard :smiley:

Wait? Does this mean that there will be less floating point errors in Blender now?

No, Howard solely updated the docs… Actually I wonder how you could come to such a conclusion.

maybe you have a clue about this. I’m adding select sharp edges to a personal menu but the selection can’t be inverted as when using the fonction in the U.I Select sharp edges fails added to a menu
ok I solved it adding a deleting line at each loop. additive selection and overriding