Float Tag Rounding

I have various query tags set up that have alarms on them. The data type is currently set to float. In my query, I round the results to 2 decimal places. However the values get stored as long slightly inaccurate floats:
image
image
This makes the alarming inaccurate. How can I make these tag values automatically store as rounded numbers?

Welcome to the wonderful world of IEEE-754 floats, where exact decimal precision doesn't exist.
32-bit wide float cannot represent 0.19 exactly:

What does this mean, exactly?

However the values get stored as long slightly inaccurate floats:

I think you misunderstand what a float is. The long value is the float representation of your decimal value. It is very accurate and will always be the same as long as it is stored as a float. The issue is that computers don't use decimal values, so when your system inputs a decimal value, it gets converted to the closest float value. Rounding the decimal value doesn't make it accurate, it makes it inaccurate. You need to work out what level of accuracy your system needs to operate on and decide on how your alarm thresholds will work.
This is why most people never have alarm conditions that rely on analog values being equal to a setpoint, and this is always done as a >= or similar.

If you want the perfect accuracy of the most simple part of the system, don't use SI units, store the count from the A/D converter that is reading your analog value in the system and only convert from that at the very last stage. That way your value is always stored as an integer.

Sorry, that's a slight misuse of the phrase. I have a screen that tracks these properties and checks if they're in spec. The script is essentially if val<limit: bad else: good. One of the limits happens to be 0.19. That float reads as out of spec even though it shouldn't. I can get around this by adding round(val, num_digits) to all of the properties, but this is cumbersome and has to be tailored to the number of decimal places each value tests to. I was hoping that there was a better way to deal with this.

If you are retrieving the values from a database, you are retrieving the 0.1899999998 value as exactly that from the database. Rounding the data is lying about the value, because you have no way to know if the value was ever 0.19, so if you round it up, you are now evaluating data for an alarm that is not real.
If you are this concerned, store all your values in the database as 100x the decimal value in an integer column in the database and divide by 100 in the query tag.

2 Likes