These are three handy functions for comparison and rounding of floating-point numbers and formatting money:
1. `bool DoubleEquals(double x, double y, double eps)` compares two double values `x` and `y` with a given epsilon value `eps` and returns a boolean value indicating if they are equal within the given tolerance.
2. `double RoundTo(double value, int digits)` rounds a double value `value` to the given number of decimal `digits`.
3. `string FormatMoney(double amount)` formats a double value `amount` as a string representing a currency amount. It formats the amount with two decimal places, replaces the decimal point with a comma, and inserts spaces every three digits for readability. It also adds the currency symbol obtained from `AccountInfoString(ACCOUNT_CURRENCY)` at the end.
Thank you so much for that. However, these functions are already implemented in the library (even with more robust results than yours), but with different names.
// Check whether two numbers are equal up to "n" digits of precision.int Compare(constdouble a, constdouble b, constint digits);
bool EqualDoubles(double a, double b, int significantDigits = 15);
bool IsClose(constdouble a, constdouble b, constint maxDifferentSignificantDigits = 2)
// accurate decimal rounding to avoid unexpected results.double Round(constdouble v);
double Round(constdoublevalue, constint digits);
double Round(constdoublevalue, constdouble step);
// Formats double with thousands separator and specified decimals.string FormatDouble(constdouble number, constint digits, conststring separator=",");
If is a bug, how to fix? If not, whats wrong in my code?
Thank you.
Print the hexadecimal representations and you will understand that the spread is far from the true real value 0.0001 (that is because round-off errors during subtraction).
jonlinper #: I expected second print to be "0.0001".
Floating-point has an infinite number of decimals. It's you, not understanding floating-point and that some numbers can't be represented exactly. (like 1/10.) Double-precision floating-point format - Wikipedia
Floating-point has an infinite number of decimals. It's you, not understanding floating-point and that some numbers can't be represented exactly. (like 1/10.) Double-precision floating-point format - Wikipedia
Dear William, thanks for the clarification, however I do not agree with you regards "infinite number of decimals". FP numbers actually have finite number of decimal digits. (For example 0.1 has exactly 52 digits after the decimal point).
What is the most optimized way to Print only significant digits with doubles.
double Trunc(constdoublevalue, constint digits);
This function works great for 99,9% of the numbers but it has issues with round numbers like 1.0000000000
My issues is that I need to strip non significant digits, and for some reason I am not able to do it using only @Trunc,
so I ended up using something like:
string Normalize_Double_ToString(double n, int d)
{
// Step 1 - it helps exclude trailing zeros
n = Round(n, d);
// Step 2 - count number of Significant Decimalsint sd = GetSignificantDecimals(n);
// Step 3 - we don't want more than specified in @dif (sd > d){ sd = d; }
// Step 4 - remove unwanted decimals without the negative random rounding double t = Trunc(n, sd);
// Debug//PrintFormat("%s [%d] [%d] :: %s", DoubleToString(n, DBL_DIG), d, sd, DoubleToString(t, sd));// Step 5 - set precisionstring s = DoubleToString(t, sd);
return s;
}
It works exactly as needed, giving me the smallest string posible for all numbers, but I was wondering if it can be optimized and still get smallest string with round numbers like 1.00000000
What is the most optimized way to Print only significant digits with doubles.
This function works great for 99,9% of the numbers but it has issues with round numbers like 1.0000000000
My issues is that I need to strip non significant digits, and for some reason I am not able to do it using only @Trunc,
so I ended up using something like:
It works exactly as needed, giving me the smallest string posible for all numbers, but I was wondering if it can be optimized and still get smallest string with round numbers like 1.00000000
Thank you
Sorry, you need to understand what are significant digits as I find your code is confusing the basic concepts.
What are you trying to do.. please explain in plain words, no code. Give example of what you find wrong and what are your expectations.
amrali #: Sorry, you need to understand what are significant digits as I find your code is confusing the basic concepts.
What are you trying to do.. please explain in plain words, no code. Give example of what you find wrong and what are your expectations.
Thx for you time, and yes, I am not totally sure I understand 'significant digits'
I basically need to 'Print' the shortest possible number. For example:
1.0000000 -> 1
1.0090000 -> 1.009
123.00100 -> 123.001
For me 'significant digits' means: digit that changes the value of a number if removed, so trailing zeros are not significant.
By the way, since Windows last update the function Round(double, int) is causing MT4 to block. The first code I posted was working perfectly and since yesterday night It completely freezes MT4 client.
Thx for you time, and yes, I am not totally sure I understand 'significant digits'
I basically need to 'Print' the shortest possible number. For example:
1.0000000 -> 1
1.0090000 -> 1.009
123.00100 -> 123.001
For me 'significant digits' means: digit that changes the value of a number if removed, so trailing zeros are not significant.
By the way, since Windows last update the function Round(double, int) is causing MT4 to block. The first code I posted was working perfectly and since yesterday night It completely freezes MT4 client.
Print() function or casting double to string like (string)dbl will get the shortest possible number of significant digits, no need to manipulate the number first. This a built-in feature in MQL. (I already proposed a fix to the developers team, and it was merged into code).
All you need to do is:
string num_str = string(number).
or, Print(number);
That is why a dedicated function to Print or format numbers to the shortest possible string is not needed inside the library, the functionality is already supported by MQL language.
Only use DoubleToString() if you need to control the number of digits after the decimal point. If digits parameter is greater than the decimal digits in your number, the 0's will be appended to the returned string, for example
DoubleToString(1.09, 5) returns the string "1.09000".
If the digits parameter is less than the number's deciaml digits, the number will be approximated, like DoubleToString(1.12345, 2) returns the string "1.12". You confusion arises from inability to differentiate numbers from strings.
Note that numbers ending in zeros like 1.09, 1.090, 1.0900, 1.09000 and 1.090000 are stored as the same Double-precision fp number in variables. These can only be achieved using direct entry by the user as manual inputs. Inside the program all those numbers are stored as the same number which is 1.09, trailing 0's are not stored.
double a = 1.09;
double b = 1.090000;
Print(a); // "1.09"
Print(b); // "1.09"
Rounding functions like round, ceil and floor changes (approximates) the input number to another number that is the nearest double number with the specified count of decimal digits after the decimal point, or the number containing the specified total number of significant digits in case of RoundToSignificantDigits().
I hope that will clear the confusion about converting double-precision fp numbers to string.
3. `string FormatMoney(double amount)` formats a double value `amount` as a string representing a currency amount. It formats the amount with two decimal places, replaces the decimal point with a comma, and inserts spaces every three digits for readability. It also adds the currency symbol obtained from `AccountInfoString(ACCOUNT_CURRENCY)` at the end.
Thank you so much for that. However, these functions are already implemented in the library (even with more robust results than yours), but with different names.
Hello @amrali, thanks for your contribution.
Maybe this is a bug?
I expected second print to be "0.0001".
If is a bug, how to fix? If not, whats wrong in my code?
Thank you.
Hello @amrali, thanks for your contribution.
Maybe this is a bug?
I expected second print to be "0.0001".
If is a bug, how to fix? If not, whats wrong in my code?
Thank you.
Print the hexadecimal representations and you will understand that the spread is far from the true real value 0.0001 (that is because round-off errors during subtraction).
So, you have to use rounding procedures.
There are sublte differences you should notice:
StripError() rounds at the 16th signifiant digit 0.00009999999999998899 (0's are not counted).
Round(x, 16) is rounding at the 16th digits after the decimal point 0.00009999999999998899
Floating-point has an infinite number of decimals. It's you, not understanding floating-point and that some numbers can't be represented exactly. (like 1/10.)
Double-precision floating-point format - Wikipedia
See also The == operand. - MQL4 programming forum (2013)
If you want to see the correct number of digits, convert it to a string with the correct/wanted accuracy.
question about decima of marketinfo() - MQL4 programming forum (2016)
Floating-point has an infinite number of decimals. It's you, not understanding floating-point and that some numbers can't be represented exactly. (like 1/10.)
Double-precision floating-point format - Wikipedia
See also The == operand. - MQL4 programming forum (2013)
If you want to see the correct number of digits, convert it to a string with the correct/wanted accuracy.
question about decima of marketinfo() - MQL4 programming forum (2016)
What is the most optimized way to Print only significant digits with doubles.
This function works great for 99,9% of the numbers but it has issues with round numbers like 1.0000000000
My issues is that I need to strip non significant digits, and for some reason I am not able to do it using only @Trunc,
so I ended up using something like:
It works exactly as needed, giving me the smallest string posible for all numbers, but I was wondering if it can be optimized and still get smallest string with round numbers like 1.00000000
Thank you
Just realized that I am using
Slightly modified version of your
and this is the code
What is the most optimized way to Print only significant digits with doubles.
This function works great for 99,9% of the numbers but it has issues with round numbers like 1.0000000000
My issues is that I need to strip non significant digits, and for some reason I am not able to do it using only @Trunc,
so I ended up using something like:
It works exactly as needed, giving me the smallest string posible for all numbers, but I was wondering if it can be optimized and still get smallest string with round numbers like 1.00000000
Thank you
Sorry, you need to understand what are significant digits as I find your code is confusing the basic concepts.
Thx for you time, and yes, I am not totally sure I understand 'significant digits'
I basically need to 'Print' the shortest possible number. For example:
1.0000000 -> 1
1.0090000 -> 1.009
123.00100 -> 123.001
For me 'significant digits' means: digit that changes the value of a number if removed, so trailing zeros are not significant.
By the way, since Windows last update the function Round(double, int) is causing MT4 to block. The first code I posted was working perfectly and since yesterday night It completely freezes MT4 client.
Thx for you time, and yes, I am not totally sure I understand 'significant digits'
I basically need to 'Print' the shortest possible number. For example:
1.0000000 -> 1
1.0090000 -> 1.009
123.00100 -> 123.001
For me 'significant digits' means: digit that changes the value of a number if removed, so trailing zeros are not significant.
By the way, since Windows last update the function Round(double, int) is causing MT4 to block. The first code I posted was working perfectly and since yesterday night It completely freezes MT4 client.