NumToStr() displays an incorrect number of Decimals [Solved]

Questions about MultiCharts and user contributed studies.
User avatar
JoshM
Posts: 2074
Joined: 20 May 2011
Location: The Netherlands
Has thanked: 1523 times
Been thanked: 1479 times
Contact:

NumToStr() displays an incorrect number of Decimals [Solved]

Postby JoshM » 24 Jun 2011

Marina Pashkova wrote:The number of decimals for a symbol is regulated through the settings in Quote Manager->Edit Symbol->Settings - Price Scale.

I came across this topic when searching for a way to return the number of decimals in a number (for example 5 for 1.56897 and three for 154.025). Below is how I solved this, and perhaps this is of use to someone else.

Code: Select all

if LastBarOnChart_s and barstatus = 2 then begin
   value34 = 1 / PriceScale;         // returns pricescale with decimals, in this case 0.001
   value35 = 0;
   
   while value35 = 0 begin
      value40 = value34 * 10;         // Multiply by 10 to step-by-step remove the decimals
      value50 = value50 + 1;         // Counter with number of multiplications
      if FracPortion(value40) = 0 then
         value35 = 1;               // If there aren't any Fractions left; break out the while loop
      value34 = value40;            // Set value 40 to the new value
   end;
   Print("The number ", (1/PriceScale):0:4, " has ", value50, " decimals.");
end;

..which returns:

Code: Select all

The number 0.0010 has    3.00 decimals.


Though I am wondering: perhaps there is a more efficient way to do this?

Regards,
Josh
Last edited by JoshM on 09 Sep 2011, edited 1 time in total.

User avatar
TJ
Posts: 6520
Joined: 29 Aug 2006
Location: Global Citizen
Has thanked: 957 times
Been thanked: 1883 times

Re: How can you remove the 3 decimal places in MC with the E

Postby TJ » 24 Jun 2011

JoshM wrote:
Marina Pashkova wrote:The number of decimals for a symbol is regulated through the settings in Quote Manager->Edit Symbol->Settings - Price Scale.

I came across this topic when searching for a way to return the number of decimals in a number (for example 5 for 1.56897 and three for 154.025). Below is how I solved this, and perhaps this is of use to someone else.

Code: Select all

if LastBarOnChart_s and barstatus = 2 then begin
   value34 = 1 / PriceScale;         // returns pricescale with decimals, in this case 0.001
   value35 = 0;
   
   while value35 = 0 begin
      value40 = value34 * 10;         // Multiply by 10 to step-by-step remove the decimals
      value50 = value50 + 1;         // Counter with number of multiplications
      if FracPortion(value40) = 0 then
         value35 = 1;               // If there aren't any Fractions left; break out the while loop
      value34 = value40;            // Set value 40 to the new value
   end;
   Print("The number ", (1/PriceScale):0:4, " has ", value50, " decimals.");
end;

..which returns:

Code: Select all

The number 0.0010 has    3.00 decimals.


Though I am wondering: perhaps there is a more efficient way to do this?

Regards,
Josh


you can reduce the calculation to this one line:

Code: Select all


decimal = Log( PriceScale ) / Log(10) ;

These users thanked the author TJ for the post (total 5):
JoshMRobotManStan BokovNW27arjfca

User avatar
JoshM
Posts: 2074
Joined: 20 May 2011
Location: The Netherlands
Has thanked: 1523 times
Been thanked: 1479 times
Contact:

Re: How can you remove the 3 decimal places in MC with the E

Postby JoshM » 24 Jun 2011

Thanks TJ! Now that's a reduction! ;)

Have a nice weekend,

Regards,
Josh

User avatar
Stan Bokov
Posts: 963
Joined: 18 Dec 2009
Has thanked: 367 times
Been thanked: 300 times

Re: How can you remove the 3 decimal places in MC with the E

Postby Stan Bokov » 27 Jun 2011

TJ wrote:you can reduce the calculation to this one line:

Code: Select all


decimal = Log(PriceScale) / Log(10) ;



Nice... :)
These users thanked the author Stan Bokov for the post:
TJ

User avatar
JoshM
Posts: 2074
Joined: 20 May 2011
Location: The Netherlands
Has thanked: 1523 times
Been thanked: 1479 times
Contact:

Re: How can you remove the 3 decimal places in MC with the E

Postby JoshM » 08 Sep 2011

TJ wrote:you can reduce the calculation to this one line:

Code: Select all


decimal = Log(PriceScale) / Log(10) ;


Hm, if I calculate the decimals and use NumToStr() to print these, I get for certain instruments (for example, USD/JPY) wrong results, even though the formula quoted above does work correctly.

Code:

Code: Select all

variables: numOfDeci(0);

numOfDeci = Log(PriceScale) / Log(10);

if LastBarOnChart_s = true then begin
   Print(getsymbolname, " Close: ", NumToStr(Close, 10), " decimals: ", numOfDeci);
   
   Print(Spaces(2), "PriceScale: ", PriceScale);
   Print(Spaces(2), "Close with calculated Decimals: ", NumToStr(Close, numOfDeci));
end;

Which gives the following output:

Code: Select all

FGBM Close: 115.9800000000 decimals:    2.00
  PriceScale:  100.00
  Close with calculated Decimals: 115.98
USD/JPY Close: 78.0290000000 decimals:    3.00
  PriceScale: 1000.00
  Close with calculated Decimals: 78.03
EUR/USD Close: 1.4475400000 decimals:    5.00
  PriceScale: 100000.00
  Close with calculated Decimals: 1.44754

As you can see, the number of decimals for the USD/JPY are calculated as 3, yet printed with 2 (output should be 78.029, not 78.03).

What's going wrong here? :)

Regards,
Josh

User avatar
JoshM
Posts: 2074
Joined: 20 May 2011
Location: The Netherlands
Has thanked: 1523 times
Been thanked: 1479 times
Contact:

SOLVED

Postby JoshM » 08 Sep 2011

JoshM wrote:The only way I can explain this NumToStr() behaviour is saying that it's a 'bug' - which actually means that I'm just out of ways to test/dissect this behaviour. :)
[...]
Anyone got an idea?

Well, it's not a bug and I got it solved (see below), but could have saved a lot of time spent "debugging" this behaviour if I knew that:

    NumToStr() uses Floor() to determine the number of decimals and not Round().

It's not in the manual or help, but well, at least now we know that. :)

Example:
Code:

Code: Select all

variables: numDeci(0), numDeciToStr(""), myValue(0), remainderStr("");

once cleardebug;

if LastBarOnChart_s = true then begin
   value1 = 1.132104982347238974239847692834;
   value3 = 10;
   
   while value3 <= 100000000000000000000000 begin
   
      numDeci = Log(value3) / Log(10);
      
      Print("Decimals: ", numDeci, "  Floor: ", Floor(numDeci), "     NumToStr(): ", NumToStr(value1, numDeci));
               
      // If there's a difference between the values, print these to string with the maximum number of decimals
      if numDeci <> Floor(numDeci) then begin
      
         Print(Spaces(3), "Decimals: ", NumToStr(numDeci, 30));
         Print(Spaces(3), "Using round in NumToStr(): ", NumToStr(value1, Round(numDeci, 0)));
      end;
   
      value3 = value3 * 10;
   end;
end;

Which gives the following output:

Code: Select all

Decimals:    1.00  Floor:    1.00     NumToStr(): 1.1
Decimals:    2.00  Floor:    2.00     NumToStr(): 1.13
Decimals:    3.00  Floor:    2.00     NumToStr(): 1.13
   Decimals: 2.999999999999999600000000000000
   Using round in NumToStr(): 1.132
Decimals:    4.00  Floor:    4.00     NumToStr(): 1.1321
Decimals:    5.00  Floor:    5.00     NumToStr(): 1.13210
Decimals:    6.00  Floor:    5.00     NumToStr(): 1.13210
   Decimals: 5.999999999999999100000000000000
   Using round in NumToStr(): 1.132105
Decimals:    7.00  Floor:    7.00     NumToStr(): 1.1321050
Decimals:    8.00  Floor:    8.00     NumToStr(): 1.13210498
Decimals:    9.00  Floor:    8.00     NumToStr(): 1.13210498
   Decimals: 8.999999999999998200000000000000
   Using round in NumToStr(): 1.132104982
Decimals:   10.00  Floor:   10.00     NumToStr(): 1.1321049823
Decimals:   11.00  Floor:   11.00     NumToStr(): 1.13210498235
Decimals:   12.00  Floor:   11.00     NumToStr(): 1.13210498235
   Decimals: 11.999999999999998000000000000000
   Using round in NumToStr(): 1.132104982347
Decimals:   13.00  Floor:   12.00     NumToStr(): 1.132104982347
   Decimals: 12.999999999999998000000000000000
   Using round in NumToStr(): 1.1321049823472
Decimals:   14.00  Floor:   14.00     NumToStr(): 1.13210498234724
Decimals:   15.00  Floor:   14.00     NumToStr(): 1.13210498234724
   Decimals: 14.999999999999998000000000000000
   Using round in NumToStr(): 1.132104982347239
Decimals:   16.00  Floor:   16.00     NumToStr(): 1.1321049823472389
Decimals:   17.00  Floor:   17.00     NumToStr(): 1.13210498234723890
Decimals:   18.00  Floor:   17.00     NumToStr(): 1.13210498234723890
   Decimals: 17.999999999999996000000000000000
   Using round in NumToStr(): 1.132104982347238900
Decimals:   19.00  Floor:   19.00     NumToStr(): 1.1321049823472389000
Decimals:   20.00  Floor:   20.00     NumToStr(): 1.13210498234723890000
Decimals:   21.00  Floor:   20.00     NumToStr(): 1.13210498234723890000
   Decimals: 20.999999999999996000000000000000
   Using round in NumToStr(): 1.132104982347238900000
Decimals:   22.00  Floor:   22.00     NumToStr(): 1.1321049823472389000000
Decimals:   23.00  Floor:   22.00     NumToStr(): 1.1321049823472389000000
   Decimals: 22.999999999999996000000000000000
   Using round in NumToStr(): 1.13210498234723890000000


Solution:
When using calculated values as input for the NumToStr() function, use Round() to ensure that the correct value gets passed, for example:

Code: Select all

NumToStr(1.1255445484, Round(myValue, 0));



Btw, I also noticed that NumToStr() has an limitation of 30 decimals - it does accept higher number of decimals, but the string that subsequently gets generated will only have 30 numbers behind the dot.

Regards,
Josh


Return to “MultiCharts”