Page 1 of 1

Workaround for DCAL Real bug

PostPosted: Sun Jun 25, 2017 3:55 pm
by dhs
Hi,

I came across a bug in the DCAL compiler when trying to hard-code a large real value: I was assigning a value of 189999.1 to a real variable, but the resulting value of the variable was -6608.9 !
I spent quite a lot of time trying to understand what was going on before I realised what was going on and the resulting a work-around for the problem. I thought I should share my experience (and the work-around) in the hope that I may save others the confusion and wasted time.

It appears that the DCAL compiler is treating the whole number part of a hard-coded real as an integer. As integers can only have values in the range -32768 to +32767, there is obviously going to be a problem if you hard-code a real number outside this range. What happens of course is that the value 'wraps around' within the allowable range of values (e.g. 32767+1 gives a result of -32768),

If I keep subtracting 64k from my hard-coded value of 189999.1 until I get a number within the allowable integer range then I end up with -6608.9 (189999.1 - 3*65536). So it is wrapping around like an integer as per my notes above.

The workaround is to avoid hard-coding individual real values outside the valid integer range. If you need to hard-code a real value outside this range then I have found 2 ways to do this:
1. Code a formula that results in your desired value, but only using values within the integer range in your formula (e.g. instead of hard coding 189999.1 you could code (32000.0 *5.0)+29999.1 or 31666.5166666667 * 6.0),
2. Hard=code the value as a string and convert it to a real value.

The following DCAL code demonstrates the above:

Code: Select allPROGRAM RealTest;
VAR
   r : real;
   tempbln : boolean;
   
BEGIN
   r := 189999.1;
   getrl (r);   ! has a value of -6608.9
   
   tempbln := cvstrll ('189999.1', r);
   getrl (r);   ! has correct value of 189999.1

   r := 31666.5166666667 * 6.0;
   getrl (r);   ! has correct value of 189999.1
   
   r :=  (32000.0 *5.0)+29999.1;
   getrl (r);   ! has correct value of 189999.1
END RealTest.