Compile Error "Using floats with a bitwise operator is not recommended"

What I REALLY want to do is convert a float to an Int32 using only functions in one line of code, so I can BITOR a bunch of these lines together (with no compile errors). Am I asking too much?

For example:

Alm_400_HeatTrace = AbsoluteValue(Truncate(TEC_100_TAB[1])) bitor
                    AbsoluteValue(Truncate(TEC_105_TAB[1])) bitor
                    AbsoluteValue(Truncate(TEC_400_TAB[1])) bitor
                    AbsoluteValue(Truncate(TEC_402_TAB[1])) bitor
                    AbsoluteValue(Truncate(TEC_616_TAB[1])) bitor
                    AbsoluteValue(Truncate(TEC_1102_TAB[1]));

My predecessor set up Float Tables (TEC_XXX_TAB) to pass info back and forth to a subroutine – the alarm state is passed back from the Subroutine as an integer dressed up as a float.

  • TEC_XXX_TAB[1] (float table) is set to a -3, -1, 0, 1, or 3 based on alarm values (lolo, lo, normal, hi, hihi).
  • I use the Alm_400_HeatTrace Int32 in PAC Display to show an icon on the Overview window if any of the alarms on the sub-window are active, one for a Warning (H or L), one for Shutdowns (HH or LL).

I’m looking for a function to effectively turn my floats into integers (without creating ANOTHER 30 variables to do it) before I use the BITOR operator to compare a bunch of these to each other. The closest thing I’ve found (so far) is TRUNCATE, but that can output an integer OR float, so I’m still getting an annoying compile error: “Using floats with a bitwise operator is not recommended”. The code appears to be working, so the Truncate must be switching the format to an Int32, but the compile errors are annoying.

Really? There’s no simple “float to int” Convert function in PAC Control? Does anyone have an elegant code solution for me? I’d like to get rid of the compile errors. Thanks!

Variable I32 = Variable FLOAT;

That’s it, unless you are trying to do something else.
So if you have a value of 1.234 then the I32 value = 1.

1 Like

Try using the Move32Bits command.

Edit
Nevermind, that isn’t going to work since this isn’t at the bit level. You will need to do it Lou_Bertha’s way.

Only two temp variables needed though:

nTemp2 = 0;
nTemp = AbsoluteValue(TEC_100_TAB[1]);
nTemp2 = nTemp2 bitor nTemp;
nTemp = AbsoluteValue(TEC_105_TAB[1]);

…

Alm_400_HeatTrace = nTemp2;

Thanks! But for that wouldn’t I have to create 30-odd Int32 variables just to absorb the value before I BITOR it? I’m looking for one simple function so I can do it all in one line without creating dummy variables.

Thanks, but same thing, @philip – wouldn’t I have to create a ton of dummy variables (one for each alarm, and there are A LOT of alarms) to use the command? I’d like to do it all in one line, and because MOVE32BITS is a command (not a function) it doesn’t return a value that I can further manipulate.

Edited my response - only two variables needed.

2 Likes

Thanks! That’s better, though still not as pretty as I was hoping… if there were a FUNCTION that only returned an INT32, then I wouldn’t have this problem. I’ll think about implementing this one… depends how annoyed I am by the Compile errors!

Have you tested that? Seems like it should return an integer.

Have you tried swapping your Truncate and AbsoluteValue around:

Truncate(AbsoluteValue(TEC_100_TAB[1]))

Good question… Per Command Help, it can return any of the “Argument 1” list, so because I’m putting it into a Float Table, the BITOR operator still thinks it’s a Float.

The code seems to work fine as written (although you might be right, that flipping the two functions may produce more predictable results due to sign bit) – I’m not sure I tested it with all the iterations of my values (-3, -1, 0, 1, 3). When I flip the two functions, the Compiler still gives me the same error. /shrug/

Looks like in order to get rid of the compile errors, I would have to resort to the 2 x dummy Int32s… not as pretty, but workable. Goes from:

Alm_400_HeatTrace = AbsoluteValue(Truncate(TEC_100_TAB[1])) bitor
                    AbsoluteValue(Truncate(TEC_105_TAB[1])) bitor
                    AbsoluteValue(Truncate(TEC_304_TAB[1])) bitor
                    AbsoluteValue(Truncate(TEC_308_TAB[1])) bitor
                    AbsoluteValue(Truncate(TEC_314_TAB[1])) bitor
                    // ~20 lines deleted here! 
                    AbsoluteValue(Truncate(TEC_798A_TAB[1])) bitor
                    AbsoluteValue(Truncate(TEC_798B_TAB[1])) bitor
                    AbsoluteValue(Truncate(TEC_1102_TAB[1]));

to (I don’t really need the Truncate, because it only ever gets set to an Int32 in the first place:

Alm_400_HeatTrace = 0;    //Int32
Alm_400_dummy_int = AbsoluteValue(TEC_100_TAB[1]);
Alm_400_HeatTrace = Alm_400_HeatTrace Bitor Alm_400_dummy;

Alm_400_dummy_int = AbsoluteValue(TEC_105_TAB[1]);
Alm_400_HeatTrace = Alm_400_HeatTrace Bitor Alm_400_dummy;

Alm_400_dummy_int = AbsoluteValue(TEC_304_TAB[1]);
Alm_400_HeatTrace = Alm_400_HeatTrace Bitor Alm_400_dummy;

etc
etc
etc

Sigh. Just not as pretty.

Thanks for the input!!!

Two quick thoughts here:

  1. Subroutine variables are local to the subroutine, so you won’t see them in the main strategy tree.
  2. Preface your dummy vars with z_ to bury them at the bottom of the tree.
2 Likes

Subroutine would certainly clean it up:

BitorFloat(Alm_400_HeatTrace, TEC_100_TAB[1]);
BitorFloat(Alm_400_HeatTrace, TEC_105_TAB[1]);

In the BitorFloat sub:

temp = AbsoluteValue(Truncate(Input));
Result = Result bitor temp;

Input is Float Literal parameter, and Result is Integer Variable parameter, temp is a subroutine integer.

2 Likes

Thanks @Beno !

  • The TEC_XXX_TAB float table is what is used to pass info back and forth to the Subroutine, so it does exist in the main strategy tree

    • [0] is the HH alarm SP (float)
    • [1] is the Alarm state in question (int32)
    • [2[ is Reset (int32)
    • [3] is “ON Time” for heater (SUB was originally written before TPOs!) (float)
    • [4] is H alarm SP (float)
  • The original code only had the HH, the alarm state, and On Time; I added some functionality for better operator visibility (which is why the elements are in such a weird order)

  • Interesting idea on the z_ – I haven’t been using it for dummy variables thus far, but I’ll keep that in mind for future Strategies… :slight_smile:

Good point! That is much nicer.

Do you guys think I would take a hit in performance by adding the Subroutine layer? The chart that this is in already runs pretty slowly for alarm code (I know, I know…)

Also, because that ends up being multiple expressions (as opposed to just one expression, like it is right now with the compile errors), the Alm_400_HeatTrace Int32 could be evaluating to multiple values over the course of running, so it could produce weird intermediate results. Ultimately if there are any HH or LL alarms in that Alarm Group, it will evaluate to 3 (0011), but it could go to 1 (0001, H or L) in the interim. Which really isn’t a big deal… it’s just used on the main window to show that an alarm exists on a sub-window for navigation purposes.

I just like clean code.

Irrelevant performance change, dev performance > processor performance. You can make it really fast with Move32Bits and evaluating the results, but no one will understand what is going on until they spend much time figuring it out. It’s better to use more processor resources and have clear code unless high performance is necessary.

Use an intermediary temporary variable and assign it at the end.

1 Like

:woman_facepalming: (I must have a case of the Mondays). Thanks!