Numeric value formatting

Ok, I feel like this should be simple, but am not finding the solution. I have several numeric values that are greater than a thousand and I do not want a comma displayed in the value. Is it possible to control that in PAC Display? Thanks in advance :slight_smile:

Check under the menu Config for Runtime Options.
There is a check box there for ‘Format Value Data with Commas’.

For more information, check out page 287 in the PAC Display Users Guide Doc 1702 (click help in Config mode).

1 Like

So all or nothing? No options at the field/value level? I think I have more fields that benefit from the comma than those that do not. I will review. Thanks Ben.

Yeah, all or nothing. The only thing you can change on a per value display is the number of decimals.

Perhaps you might like to manipulate the values in PACControl, using the instructions:

[B]FloatToString[/B](Convert, Length, Decimals, Put Result in)
[B]NumberToString[/B](Convert, Put Result in)

to move the numerical values into strings and then strip the offending commas and decimal points with some extra string handling commands such as.

[B]FindCharacterInString[/B](Find, Start at Index, Of String)
[B]SetNthCharacter[/B](To, In String, At Index)

Not the easiest way of handling this in the world, but a single subroutine would serve for all similar cases in the project.

If you update this routine as fast as you are reading the values, then no-one will know that the values have been converted into text fields.

I like it! That will totally work. Thank you :slight_smile:

Thanks, gmitchell, good points! There’s also the new-ish [B]TrimString[/B] command, which could be handy too.

On a related note, a customer just asked about formatting a float into scientific notation in PAC Display.

I told him about using [B]NumberToString[/B] in his logic, then displaying the resulting string, as we discussed above.

He specifically asked for the format 1.23E-08 but [B]NumberToString [/B]gives you: 1.234567e-08. (With a four more places after the decimal point, and a capital E – which might be okay, I’ve not yet heard back from him.)

In the meantime, for grins and giggles, I pondered how to adjust for that w/a couple of OptoScript lines ALMOST work perfectly:

NumberToString(fGauge, sGauge);

// drop the 4 extra characters and convert the lower-case e to upper case E
// "1.333000e+03"
GetSubstring(sGauge, 0, 4, sSignificand);
GetSubstring(sGauge, 9, 3, sExponent);


// put the piece together and replace that e with an E
sGaugeHMI = sSignificand + "E" + sExponent;

I say [I]almost [/I]because… and I could be thinking too hard about this but… do you see why it might work for 1.33E+03 but not 0.6666666 ?

That method effectively truncates at the least significant digit. Which might also be okay for him, given the specific numbers he sent me.

But just in case, I came up with a few more lines of OptoScript, but it’s getting kind of ugly. Wondering if anyone else out there in OptoLand as a more elegant way of formatting a float value to a specific number of significant digits in that significand/mantissa for scientific notation?

Here’s the longer version which does a Round at the 1/100ths place:

NumberToString(fGauge, sGauge);


// That gives us a string in this format: "1.333000e+03" 
// but we only want 2 sig digits, so let's convert the e to a space so we use the StringToFloat and Round comamnds
sGauge[8] = ' '; // SetNthCharacter works too


fGaugeX100 = StringToFloat(sGauge) * 100; // now we should have a value like 133.3
fGaugeX100 = Round( fGaugeX100 );


NumberToString(fGaugeX100, sGaugeX100); 


// drop the 4 extra characters and convert the lower-case e to upper case E
// "1.333000e+03"
GetSubstring(sGaugeX100, 0, 4, sSignificand);
GetSubstring(sGauge, 9, 3, sExponent);


// put the piece together and replace that e with an E
sGaugeHMI = sSignificand + "E" + sExponent;


Clear as mud? Other ideas/suggestions?

Would suggesting Opto22 makes a printf like command with full format specifiers be out of the question? :slight_smile:

Nope, good idea! That thought had occurred to me too, especially since you know there’s a printf under the hood there if you go deep enough…

Anyway, I will add a “feature request” ticket!

Is there really a printf() like function built-in / hidden in Control’s script editor…?

I think she meant that the PACs “OS” has a printf library function available to it, it just isn’t exposed to any Optoscript command. Is the OS written in C? Where does Forth come in?

I worked on a little subroutine for this the past few nights - put it in the Code Samples section.[URL=“http://www.opto22.com/community/showthread.php?t=1372&p=4456”]

http://www.opto22.com/community/showthread.php?t=1372&p=4456

Thanks, philip, for sharing your excellent example/sub!

And yes, that’s what I meant. The part of what’s needed for such a feature was built into the firmware only at the same time as we added the new-ish “Trim” PAC Control command. The missing PAC Control piece is on the wish list but that’s a long list.

The firmware itself is written in mostly C/C++ (some of it by me, even!) and a big chunk of that (what we call the “control engine”, vs. the MMP part) is essentially a Forth interpreter. So when you compile your Strategy, PAC Control creates Forth code which gets downloaded interpreted by that control engine. Usually the Forth is not something users would have to worry about since the idea of our flowchart-based approach is you don’t have to be a programmer and worry about all that icky syntax and what-not!

Since you’ve already asked about how the watch works, and I can tell you WAY more than you need/want to know… some OptoFans may end up touching the Forth stuff a little if:

  1. you use the “initialize on download” option for variables; you’ll see a tiny bit of Forth in the PAC User’s guide, under “Setting Initial Values”
  2. you use this [B][U]peer-to-peer[/U][/B] example, where I include some subroutines that talk directly to that Forth interpreter. But that’s like “void the warranty” stuff that can really cause trouble so we don’t normally recommend…

I had a customer that wanted Exponents values to show on display when below zero
I created code below and it works in groov to display the Exponent Value but will only execute if value changes
I commented the code
Enjoy

if (floatx <0 ) then // show exponent only if less than Zero
       if (floatLast <> Floatx) then  //  do the conversion if the value has changed
           floatlast = floatx;
           FloatToString(floatx, 12, 9, exp);  // make a 12 char string with 9 decimal places
          //first character [0] will be negative sign "-" ascii 45
          //next character  [1] will be zero ascii 48 
          //next character  [2] will be decimal point "." ascii 46 
          //next character  [3] may be a leading zero or ascii 48  start looking in 3
          expVal = 1;  //set start of exponent count
          CNT = 3;     // set Counter to start Looking
          NonZero = 0;  // flag for non zero char found
         While (nonzero == 0 or CNT > 11)   
             asciiVal = GetNthCharacter(exp, CNT);  // get next char 
             if (asciiVal == 48) then // first val is 0
             incrementvariable(ExpVal);
             incrementvariable(CNT);  // chk for next 
             else 
             NonZero = 1;    // when first non zero found set flag
             GetSubstring (exp, CNT, CNT + 1, FirstNon0);  //get the first Whole exponent value
             endif
          wend
          //non zero found
          asciiVal = GetNthCharacter(exp, 11);
             if (asciiVal == 48) then // if last value is 0  then Ignore
             remVal = 11 - 1;  //reduce the remainder of characters by 1
             endif
             asciiVal = GetNthCharacter(exp, 10);
             if (asciiVal == 48) then // if second last value is 0  then Ignore
             remVal = Remval - 1;  // reduce remainder value by 1
             endif
             remainderChar = RemVal - CNT;  // calculate the remainder of string characters
          GetSubstring (exp, CNT +1, remainderChar, FirstE);  // get the exponent value after decimal
          NumberToString(expVal, ExpValS);  //create the exponent string 
          FirstE = "-" + FirstNon0 + "." + FirstE + "e" + expVals;  //format the string
          DegK =  Floatx + KelvinConvert;
      endif
endif
1 Like