i have two double arrays, let's say A and B. i want to compare their results to 7 significant digits. will the following be correct to make the comparison?
k = pow(10,7);
for(...)
{
if(((int)A[i]*k)!=((int)B[i]*k))
{
...
}
}
i have two double arrays, let's say A and B. i want to compare their results to 7 significant digits. will the following be correct to make the comparison?
k = pow(10,7);
for(...)
{
if(((int)A[i]*k)!=((int)B[i]*k))
{
...
}
}
In order to compare doubles, you could use something like this:
bool fequal(double a, double b)
{
return fabs(a-b) < epsilon;
}
Taken from here.
fabs
reference.
But make sure you understand the potential pitfalls.
No, this will not work.
The type cast operator has higher precedence than the multiplication operator. This means that A[i]
and B[i]
will be cast to integers (and be truncated) before being multiplied by 1e7. 2.25 and 2.5 will end up being equal to your code. You can fix that by putting the multiplication in parentheses: (int)(A[i]*k)
Also, since you're relying on truncation instead of rounding, you may end up with incorrect results (depending on what you're expecting). 1.0e-7
and 1.9e-7
will be equal (1 == 1
), while 1.9e-7
and 2.1e-7
will not (1 != 2
). I suggest finding a function that will round properly with the behavior you desire.
Also, your comparison does not deal with significant digits, it simply changes the value of the exponent. In the above examples, there are only 2 significant digits, however your code would only compare one of those digits because the value of the exponent is -7.
Here is some code that does what you want:
//create integer value that contains 7 significant digits of input number
int adjust_num(double num) {
double low_bound = 1e7;
double high_bound = low_bound*10;
double adjusted = num;
int is_negative = (num < 0);
if(num == 0) {
return 0;
}
if(is_negative) {
adjusted *= -1;
}
while(adjusted < low_bound) {
adjusted *= 10;
}
while(adjusted >= high_bound) {
adjusted /= 10;
}
if(is_negative) {
adjusted *= -1;
}
//define int round(double) to be a function which rounds
//correctly for your domain application.
return round(adjusted);
}
...
if(adjust_num(A[i]) == adjust_num(B[i])) {
...
}
Yes but you do have to make one change. try (int)(A[i]*k) to make sure that your multiplication get executed first.
Hope this helps.
When you are using two floating-point values to decide if the values they would ideally have are equal, you should have some estimate (or, better, a proven bound) of how far apart the calculated values could be if the exactly calculated values were equal. If you have such a bound, then you can perform a test like this: “If the two numbers are closer together than the error bound, then accept them as equal.” The error bound could be a single absolute number, or it could be a number relative to the magnitude of one of the values, or it could be some other function of the values.
However, there is another question you should answer. Sometimes, the above test will accept values as equal (because the two calculated values are close together, possibly even equal) even though the exactly calculated values would not be equal. So, you know whether accepting calculated values that are close to each other as equal even though the exactly calculated numbers are not equal will cause you problems. If the answer is yes, the above test will sometimes accept as equal numbers that will cause you problems, then you cannot use this test. You may have to perform your calculations a different way to reduce the errors.
Advice is often given to fabricate some seemingly small threshold and use it. This is sloppy programming and is not engineering.
As an aside, never write pow(10, 7)
. Write 1e7
. This avoids any possibility of error in the function call and it may avoid an unnecessary functional call entirely.