How to convert a floaring value to two integers in DeltaV?

This is to write a command to a floboss computer, because the floboss reads in another way than deltaV, (Most and least words)

  • In reply to lsocorro:

    Could you repost this link please?
  • In reply to Andre Dicaire:

    Since this helped me figure out how to write the code I figured I would share it here to make it easier on some one else. The code is not bullet proof but it will get you on the right path.

    REM Figure out what the sign bit is. SGN is Boolean type parameter.
    '^/SGN.CV' := ('^/FLOAT.CV' < 0)?1:0;
    REM Figure out the exponent part. EXPONENT is signed 8 bit integer parameter.
    '^/EXPONENT.CV' := -127;
    WHILE ((2 ** '^/EXPONENT.CV') > '^/FLOAT.CV' OR (2 ** ('^/EXPONENT.CV' + 1)) < '^/FLOAT.CV') AND '^/EXPONENT.CV' < 128 DO
    '^/EXPONENT.CV' := '^/EXPONENT.CV' + 1;
    END_WHILE;
    REM Figure out mantissa. MANTISSA is 32 bit unsigned integer.
    '^/MANTISSA.CV' := (('^/FLOAT.CV' - (2 ** '^/EXPONENT.CV')) / (2 ** '^/EXPONENT.CV')) * 8388608;
    REM Put bits in their correct spots for two integers.
    '^/MSW_OUT.CV' := SHL((SHL('^/SGN.CV', 9) | '^/EXPONENT.CV' + 127 ), 7) | SHR('^/MANTISSA.CV',16);
    '^/LSW_OUT.CV' := '^/MANTISSA.CV' & 65535;

  • In reply to Virginijus Vaiciulis:

    Virginijus, Thanks for sharing?

    DeltaV uses 32 bit floating point with a Mantissa of22 bits, so the mantissa parameter would be a 32 bit Unsigned Integer, which I think you did use as you shift this 16 bits for the MSW_OUT. So likely just a commenting error.

    I would first check to see if number is fraction or not. No need to check -127 to 0 if the absolute value is larger than 1. and vice versa. There are various techniques to minimize the number of functions executed. Since the number can be anything, the brute force method means more CPU, possibly 256 iterations to find the exponent. If you use this expression somewhat extensively, CPU could be impacted. If most of the data is expected to be larger than 1, then avoid 127 iterations. You could also check several additional milestone values like, IF ABS(FLOAT) > 2**60, and 2**30 or 2**90, and then finish with an orderly count. Within three if statements, you narrow the exponent to within 30 possible values to loop through, instead of 256.

    I also think I would use an internal variable for While-Do loop. Then Output the final value to the ^/EXPONENT parameter. However, this may be due to a misperception on my part. I have not tested this lately, but I recall that if I wrote to a parameter and read that parameter in the same scan the value read would not be the expected value I just wrote. Written value would be updated at the end of the expression scan and available on the next scan. So I have taken to using an internal variable for things like an index in a While-Do loop, or iterative calculation. The result is then written to a parameter. Maybe this is no longer an issue, but once you have something that works, you tend to stay with it. If your expression is indeed working to determine the correct exponent, they my misconception has been confirmed. Thanks.

    Andre Dicaire

  • In reply to Andre Dicaire:

    Corrected the error in the comment from 16 to 32 unsigned integer for mantissa. The code works but definitely can be improved upon.
  • In reply to Andre Dicaire:

    Andre, thanks for constructive criticism. Obviously I can't do math without my glasses. Not sure why I had While-Do loop in there in the first place.

    REM Figure out what the sign bit is. SGN is Boolean type parameter.
    '^/SGN.CV' := ('^/FLOAT.CV' < 0)?1:0;

    REM Figure out the exponent part. EXPONENT is signed 8 bit integer parameter.
    '^/EXPONENT.CV' := TRUNC(LOG2(2, ABS('^/FLOAT.CV')));

    REM Figure out mantissa. MANTISSA is 32 bit unsigned integer.
    '^/MANTISSA.CV' := (('^/FLOAT.CV' - (2 ** '^/EXPONENT.CV')) / (2 ** '^/EXPONENT.CV')) * 8388608;

    REM Put bits in there correct spots for two integers.
    '^/MSW_OUT.CV' := SHL((SHL('^/SGN.CV', 9) | '^/EXPONENT.CV' + 127 ), 7) | SHR('^/MANTISSA.CV',16);
    '^/LSW_OUT.CV' := '^/MANTISSA.CV' & 65535;
  • In reply to Virginijus Vaiciulis:

    Well, I think I may have suggested a clever solution, but you definitely found a more intelligent one. Love it.

    Andre Dicaire