I disagree.
Using significant digits allows for great flexibility in our comparison. For instance if sd = 4 then the two variables are considered equal if the difference between them is 1/10000 of the numbers being compared, if sd = 6 then it would be 1/1000000. This will work irrespective the magnitude of the numbers being compared.
The sketch below is an improvement on my original code in that the programmer can select between significant digits or a simple distance (measure of closeness) when performing the test. It seems to me that one or other of these functions can be used in any algorithm where there is a need to test for equality between floating point numbers.
With regard to your suggested approach requires the number to be converted to a string during the process and this introduces other problems
- Converting a number to a string is programming language dependent
- The string representation for floating point numbers can depend where in the world the program is running. For example, in France the comma (
,
) is used as the decimal separator
- Processing and Java provide a number of methods to convert a number to a string with different results.
- Very large and very small numbers use scientific notation so
1.23E35
is a valid string representation of a large floating point number. Your approach would have to handle these also.
Still it is always fun to think of new or alternative ways to do things
void setup() {
// These test pass a integer as the third parameter so is treated as 'disgnifcant diigits'
println("User specifies number of significant digits");
testIsClose(1.201, 1.202, 4);
testIsClose(1201, 1202, 3);
testIsClose(0.0034567, 0.0034567, 6);
testIsClose(12345678, 12345679, 7);
testIsClose(-sqrt(2)*sqrt(2), - 2, 8);
// These pass a float as the third parameter so treated as a measure of closeness
println("\nUser specified closeness factor");
testIsClose(12345676, 12345678, 1f);
testIsClose(-sqrt(2)*sqrt(2), - 2, 1e-6);
exit(); // we are done so close sketch window
}
/*
These are the two methods used to test for exactness they use method overloading.
If the third parameter is an integer then it will be treated as the number of
significant digits and the first method is executed.
If the third parameters a float then it will be treated as the measure of
closeness or maximum distance allowed between the variables
*/
boolean isClose(float num1, float num2, int sd) {
return abs(num1 - num2) <= max(abs(num1), abs(num2)) / pow(10, sd);
}
boolean isClose(float num1, float num2, float epsilon) {
return abs(num1 - num2) <= epsilon;
}
// Utility functions to test the isClose() function
void testIsClose(float n1, float n2, int sd) {
boolean result = isClose(n1, n2, sd);
if (result)
println(n1, " is close to ", n2, " using ", sd, " significant digits");
else
System.err.println(n1 + " and "+ n2 + " are not close using "+ sd + " significant digits");
}
void testIsClose(float n1, float n2, float epsilon) {
boolean result = isClose(n1, n2, epsilon);
if (result)
println(n1, " is close to ", n2, " using ", epsilon, " as closeness factor");
else
System.err.println(n1 + " and " + n2 + " are not close using " + epsilon + " as closeness factor");
}