Bug in string() function. Wrong conversion of float -> string

 

Forum on trading, automated trading systems and testing trading strategies

MT5/mql5 reported and confirmed bugs.

amrali, 2022.02.17 15:33

Bug in string() function. Wrong conversion of float -> string.

Build 3211 but this is not specific to this build, it's an old one.

A bug is found in string() function where wrong conversion of float -> string.

If you convert an arbitrary single-precision floating-point number to a decimal string, and then convert that back to floating-point, you should recover the original floating-point number. In other words, the conversion will round-trip.

The string() function may return wrong string representation of float numbers that cannot round-trip into the same numeric value.

This also affects implicit casts inside Print(), Alert(), Comment(), FileWrite().

The absence of 1:1 mapping will bring much uncertainty regarding the printed single-precision floating point numbers .

Therefore, what you see is NOT what you get.

void OnStart()
  {
   Print(1.2f);
   Print(1.200001f);
   Print(1.200002f);
   Print(1.200003f);
   Print(1.200004f);
  }

// Output:
// 1.2
// 1.2
// 1.2
// 1.2
// 1.2

This is a sample script to reproduce the bug:

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnStart()
  {
   int fails = 0;
   int count = 1000;

   for(int i = 0; i < count && !IsStopped(); i++)
     {
      float number = (float)(MathRand() / 32768.0) * (1 + FLT_EPSILON);

      // Bug in string() function. wrong conversion of float -> string.
      string str = (string)number;

      // If the original number cannot be recovered, this confirms the bug.
      if(number != (float)str)
         fails++;
     }

   printf("Build %i: Tested %d float values", TerminalInfoInteger(TERMINAL_BUILD), count);
   printf("MQL5 string() conversion failures: %d", fails);
  }
//+------------------------------------------------------------------+

// Sample output:
// Build 3211: Tested 1000 float values
// MQL5 string() conversion failures: 993

And, here is a temporary solution until the bug is fixed:

//+------------------------------------------------------------------+
//| Converting float value into the shortest string representation   |
//| that round-trips into the same numeric value. This ensures that  |
//| a float value converted to a string is always parsed back into   |
//| the same numeric value. i.e., (float)(Repr(f)) == f.             |
//+------------------------------------------------------------------+
// toString()
string Repr(float value)
  {
//--- https://stackoverflow.com/a/35708911/4208440
//--- https://www.exploringbinary.com/number-of-digits-required-for-round-trip-conversions/
//--- Try format with 6, 7, 8, 9 spaces of precision to return the shortest
//--- decimal numeric string which round-trips to the specified value.
   string repr = "";
   for(int prec = 6; prec < 10; prec++)
      if(value == float(repr = StringFormat("%.*g", prec, value)))
         break;
   return repr;
  }

void OnStart()
  {
   Print( Repr(1.2f) );
   Print( Repr(1.200001f) );
   Print( Repr(1.200002f) );
   Print( Repr(1.200003f) );
   Print( Repr(1.200004f) );
  }

// Output:
// 1.2
// 1.200001
// 1.200002
// 1.200003
// 1.200004


This bug is also causing another strange behavior in the display of single-precision float values (input parameters) in dialogue boxes:

Compile and run this script:

#property script_show_inputs

input float float1 = 0.1f;
input float float2 = 1.2f;

void OnStart()
  {
  }

That is what I got when I tried to run it:




Reason: