# Precision of Math Node?

To normalize the position coordinates of particles for an Image Texture node, I have to divide 1 by a very large number (119,617). After running some tests, I see that the colors of my image texture are off by a factor of about 1e-4 (0.0001).

This has me wondering: how many decimal places does the Math node retain in its output?

I've noticed that some fields (e.g., the values for a Divide operation) accept up to three decimal places (and that everything beyond that third decimal place is simply rounded up or down). Is the same true for the output of the Math node? If so, is there anyway to change the output precision so that I get at least 6 decimal places in my output?

Many thanks if you know the answer and care to share it!

EDIT: Jaroslav pointed out that color is shown in the Data-Blocks view of the Outliner panel with six decimal places. However, when I look at the same view of my outliner, I see only three decimal places. Compare my screenshot (below) to that posted by Jaroslav. This is under Blendfile Data > Images > StarCol > Pixels.

Is there a reason for this difference? Am I looking in the wrong place in the Data-Blocks view? Can I trust that under the hood the full RGBA color values are being used (at least to six decimal places)? I would post this in a separate question, but as I'm only asking for clarification, it seemed best to do it here. Thanks again!

EDIT 2: The Python output for the pixel color values, on the other hand, has far more decimal places than just six! I assume that the values shown in the Outliner panel and in the fields of the Math node are shown with three decimal places for conciseness only? It would be disappointing to have the full precision stored in the Blender file and not using it!

• The UI shows rounded values for practical purposes of displaying a large number in a limited space, that doesn't mean the values are rounded internally at render time – Duarte Farrajota Ramos Aug 17 '18 at 8:28
• Thank you all for commenting! I just learned a few very useful things and started thinking about some important matters, like how numbers are represented and handled in Blender, and how to avoid running into issues of precision when I eventually start working with millions of particles. Thanks!! – Alex Aug 17 '18 at 21:12
• The numbers that you see in Python console may not be precise. They are approximations converting back from binary to decimal numbers. There is no more precision, there are only more digits that at some point start to differ from the original value that needed to be stored as binary number that could not fit into the 32 bits because it was an infinite sequence for example. – Martynas Žiemys Aug 18 '18 at 9:12
• I was rendering into 32bit .exr, maybe that's why in my screenshot there are more decimal places displayed. In the console you can take seriously 7 decimals, the rest is not precise. – Jaroslav Jerryno Novotny Aug 21 '18 at 23:10

For values Blender uses IEEE single precision floats. This gives a precision of about 7 decimal digits. The displayed value is rounded to 3 decimal places and the displayed value when editing the field to 6 decimal places (probably because the precision limitations).

The RMB value viewer in image editor of render output is rounded to 5 decimal places, but render values will render in full 32bit. Stored and rounded in format you choose.

It is also unlikely you are experiencing limitations in floating point representation:

$1/119617 = 0.000008360015716829547$

When rendering this and storing with 32bit .EXR you get:

A sampled value of 0.00001 in Image Editor (5 decimal rounding), a value of 0.000008 in Data-Blocks outliner view (6 decimal rounding):

And value of 0.000008360016181541141 that is saved in the file by inspecting it through the console:

That's an error of 0.00000000000046471159

All of these cannot explain the 0.0001 error you are seeing. The problem is somewhere else than in precision of Blender math or your math is more complicated than what it seems and your floating point limitations snow-balled into the 0.0001 error.

• Thanks for the thoughtful reply! I learned at least three things from your post. I honestly don't know where the error is coming from—strictly wondering if it could be the Math nodes. Part of the problem has been that I don't know how to check the values of things in Blender. Knowing that I can use Python code and the Outliner panel for that will help! – Alex Aug 17 '18 at 21:04
• Inaccurate. Rounding of stored values of Math node has nothing to do with decimal places it's only displayed that way. Values of the node can easily be checked by creating a Math node in the material of the first material slot of the active object and typing: 'bpy.context.object.material_slots[0].material.node_tree.nodes['Math'].inputs[0].default_value' into the Python Console. A value like 0.0000000008 will be stored as 8.000000106811456e-10. – Martynas Žiemys Aug 17 '18 at 22:35
• @MartinZ I am glad you checked that with console, but it's not that easy, you were lucky with that number. This is pandoras box - if you input 0.5555555555 you get 0.5555555820465088 back. Usually the error is on the 7th decimal place, sometimes on the 6th. Looks like rounding but its weird, because its not consistent. When you click the inputted value in the node to see it and then click away you get 0.5555559992790222, which is another weirdness and still not even Decimal(0.555556). I guess the devs know about artifacts after 6th decimal place and that's why you get that in the UI. – Jaroslav Jerryno Novotny Aug 17 '18 at 23:07
• @MartinZ I tested this before writing the answer, but decided to omit this to keep my answer simpler. My findings were anything after the 6th place cannot be trusted and it looks like rounding with some noise to it. If anybody has explanation why this is, I'll be happy to find out. – Jaroslav Jerryno Novotny Aug 17 '18 at 23:11
• I believe this is because of decimal to binary conversion. If there are more digits in the number before the decimal it changes things up as well. As I understand there are many different ways to store floats, maybe the one used here is not that efficient or maybe these are not full 32bit floats. I guess without looking at the source code it will be hard to tell. In any case it seems it's a precision error. Not much context was provided, I think it is likely that the error gets multiplied somewhere in the process. It seems there is not enough information to reach any definite conclusion. – Martynas Žiemys Aug 17 '18 at 23:28

Float data in blender are stored as 32bit floats:

The reason that you see third decimal place is that blender round float value in widget, but not in memory:

• Awesome—I'm cool with having the nodes showing only three decimal places if under the hood we are preserving the full number (or at least a few more decimal places beyond just three). Thanks! – Alex Aug 17 '18 at 21:11

There is no way to change the precision of the values. They should be 32bit floats. I think the problem you are experiencing is not precisely about decimal places. The way I understand it, it is about binary precision. Numbers are stored in binary and a lot of finite fractions in decimal format can only be expressed as infinite fractions in binary for example decimal 0.1 will be repeating infinite fracture in binary: 0.00011001100110011... so it will actually be stored as an approximate value. The actual way numbers are stored is more complex than it seems. You can search for something like '32bit float' to find out more about it. However the problems with precision remain.

You will have to come up with another way to do what you are doing if more precision is needed. It might be useful to post another question describing what exactly you are trying to do when you face this issue. The solution might be possible at another point in your workflow.

• For sure I'll have to learn more about how numerical values are stored and handled in Blender. Thanks for pitching in and getting me to think about these matters. I... think that maybe 119,617 pixels is more than I should have in a single row and will be looking into splitting that into multiple rows each with fewer pixels (which should give larger fractions less susceptible to rounding-off errors). – Alex Aug 17 '18 at 21:09

Thank you all for the very thoughtful replies. I have a better sense of what's causing the error and I figured I'd share for those in the future who experience this.

The problem has nothing to do with numerical errors. I learned a lot about numerical precision and some best practices to keep in mind, like using 32-bit EXR image textures for very large particle systems to avoid rounding-off errors, but I'm happy to say that my issue has to do with the particle index itself.

The real problem is probably that I went on the assumption that the index of a particle would match that of the underlying vertex (from which it is generated). But, it seems, at least for some particles, that is not the case.

I checked the actual location of a specific particle (#32263, the Hipparcos catalog number for Sirius A), and compared it to that of vertex 32263. Turns out the two are in different places on my screen.

I also checked which vertex the particle coordinates correspond to. It's vertex 32250, or minus 13 positions left of 32263—precisely the error I had observed for this star (which, mysteriously to me until now, had been getting its color from a pixel 13 positions left of where I expected it to be).

I haven't corrected the issue yet—now I have to figure out why the particle and vertex indices don't match (I guess they generally don't?) and see if I can constrain them to be the same—or, if I can't, at least figure out how to map the particle indices to the vertex indices (a must, since the vertex indices match the Hipparcos catalog indices, which I need to retrieve the star properties in my Python script).

Hope this helps someone in the future and thanks everyone again for patiently writing your responses. I learned things.