sliu152: I'm trying to get the number of decimal digits from a number.
|
|
Sadly, the digits_in method cannot be used readily for doubles as they occur during runtime.
For debugging purposes I have rewritten the code like this:
int DigitsIn(double d){ double tempDouble = d; if (tempDouble > 1.0) tempDouble -= int(tempDouble); int digits = 0; double subtract = tempDouble - int(tempDouble); while(subtract > 1.E-8) { tempDouble *= 10.0; subtract = tempDouble - int(tempDouble); ++digits; } return digits; }
If you have an incoming double value that is e.g. "1.11544" you need to first reduce it it so the double becomes "0.11544"
But during debugging the incoming double has an actual representation of: "0.115439999999999987" which leads to an endless loop of that code.
Not sure if this can be solved in an elegant way, other than managing the number of digits manually?
This is what I use. There's a maximum of 8 to keep it at a reasonable level.
int CountDigits(double val) { int digits=0; while(NormalizeDouble(val,digits)!=NormalizeDouble(val,8)) digits++; return digits; }
Probably a bit more time consuming than calculating the remainder.
Probably a bit more time consuming than calculating the remainder.
This becomes an interesting illustration of interpreted versus compiled languages. In MQL4 (interpreted), the following function is - to my surprise - slightly faster on average than the use of NormalizeDouble():
int CountDigits(double val) { // If precision can be reduced, e.g. to 6, then the function // becomes slightly faster on average. int precision = 8; val = MathAbs(val); string x = DoubleToString(val - MathFloor(val), precision); int pos = StringFind(x, "0", 2); return (pos > 0 ? pos - 2 : precision); }
But in MQL5 (compiled), this processing via string conversion is massively slower than the use of NormalizeDouble().
Works like a charm @lippmaje - thanks for sharing!
A small recommendation here: If you improve the signature it allows some client code to adjust the precision - if necessary:
int CountDigits(double val, int maxPrecision = 8) { int digits = 0; while(NormalizeDouble(val,digits) != NormalizeDouble(val, maxPrecision)) digits++; return digits; }
JC: Thanks for measuring the computational time! Good to know that NormalizeDouble doesn't perform too bad in MQL5.
@JC @Marcel, great.
We could write it like this to make it a tad faster:
int CountDigits(double val, int maxPrecision = 8) { int digits = -1; double maxp = NormalizeDouble(val, maxPrecision); while(NormalizeDouble(val, ++digits) != maxp); return digits; }
Hi,
I'm trying to get the number of decimal digits from a number.
for example
0.1234 ---> 4
0.465 ---> 3
0.51 ---> 2
So far, I can only a similar function from this function
But that doesn't really help me. I need to get the number of decimal digits which I get from
So if I get '0.01' the output will be '2'
What to do ?
This becomes an interesting illustration of interpreted versus compiled languages. In MQL4 (interpreted), the following function is - to my surprise - slightly faster on average than the use of NormalizeDouble():
But in MQL5 (compiled), this processing via string conversion is massively slower than the use of NormalizeDouble().
What allow you to say mql4 is interpreted ? As far as I know since build 600, it's compiled like mql5.
It's more of a continuum than a pair of binary categories, but if MQL4 is truly "compiled" then it's clearly a different class of compilation to MQL5.
- .ex4 files are much smaller than the .ex5 equivalents
- MetaEditor builds/compiles .ex4 much faster than .ex5, suggesting that it's doing much more complex work with MQL5.
- The compiler is much cleverer in MQL5.
As an example of 3, take the following function which I initially used to compare speeds between MQL4 and MQL5:
int res; double y = 1.11354; for (int i = 0; i < 1000000; i++) { res = CountDigits(y); }
In MQL5, the timings clearly indicate that the compiler collapses this into a single call rather than 1,000,000 iterations of the loop. It is clearly detecting that the calculation inside the loop is constant, and only runs it once. But in MQL4 it does run the loop 1,000,000 times.
If you add the following line inside the loop...
y += 0.00001;
... then it makes, as expected, almost no difference to the speed of the MQL4 code, but does massively increase the time taken by the MQL5 code - because it's now presumably doing 1,000,000 loop iterations rather than 1.
Similarly, lippmaje's CountDigits() function is so much faster on MQL5 than MQL4 that it looks very much like the difference between native code vs p-code.
It's more of a continuum than a pair of binary categories, but if MQL4 is truly "compiled" then it's clearly a different class of compilation to MQL5.
- .ex4 files are much smaller than the .ex5 equivalents
- MetaEditor builds/compiles .ex4 much faster than .ex5, suggesting that it's doing much more complex work with MQL5.
- The compiler is much cleverer in MQL5.
As an example of 3, take the following function which I initially used to compare speeds between MQL4 and MQL5:
In MQL5, the timings clearly indicate that the compiler collapses this into a single call rather than 1,000,000 iterations of the loop. It is clearly detecting that the calculation inside the loop is constant, and only runs it once. But in MQL4 it does run the loop 1,000,000 times.
If you add the following line inside the loop...
... then it makes, as expected, almost no difference to the speed of the MQL4 code, but does massively increase the time taken by the MQL5 code - because it's now presumably doing 1,000,000 loop iterations rather than 1.
Similarly, lippmaje's CountDigits() function is so much faster on MQL5 than MQL4 that it looks very much like the difference between native code vs p-code.
Ok thanks for your answer, I will not argue as anyway we will never know what is really behind the scene.
By the way, mql5 compiler optimizations can be disabled.
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Hi,
I'm trying to get the number of decimal digits from a number.
for example
0.1234 ---> 4
0.465 ---> 3
0.51 ---> 2
So far, I can only a similar function from this function
MarketInfo(Symbol(),MODE_DIGITS);
But that doesn't really help me. I need to get the number of decimal digits which I get from
MarketInfo(Symbol(),MODE_LOTSTEP);
So if I get '0.01' the output will be '2'
Any suggestion will be greatly appreciated.
Thank you in advance